mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Merge branches 'tracing/ftrace', 'tracing/hw-branch-tracing' and 'linus' into tracing/core
This commit is contained in:
		
						commit
						e36b1e136a
					
				
					 191 changed files with 11706 additions and 1188 deletions
				
			
		| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
# To add a new book the only step required is to add the book to the
 | 
			
		||||
# list of DOCBOOKS.
 | 
			
		||||
 | 
			
		||||
DOCBOOKS := z8530book.xml mcabook.xml \
 | 
			
		||||
DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
 | 
			
		||||
	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
 | 
			
		||||
	    procfs-guide.xml writing_usb_driver.xml networking.xml \
 | 
			
		||||
	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										418
									
								
								Documentation/DocBook/device-drivers.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										418
									
								
								Documentation/DocBook/device-drivers.tmpl
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,418 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
 | 
			
		||||
	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
 | 
			
		||||
 | 
			
		||||
<book id="LinuxDriversAPI">
 | 
			
		||||
 <bookinfo>
 | 
			
		||||
  <title>Linux Device Drivers</title>
 | 
			
		||||
 | 
			
		||||
  <legalnotice>
 | 
			
		||||
   <para>
 | 
			
		||||
     This documentation 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.
 | 
			
		||||
   </para>
 | 
			
		||||
 | 
			
		||||
   <para>
 | 
			
		||||
     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.
 | 
			
		||||
   </para>
 | 
			
		||||
 | 
			
		||||
   <para>
 | 
			
		||||
     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
 | 
			
		||||
   </para>
 | 
			
		||||
 | 
			
		||||
   <para>
 | 
			
		||||
     For more details see the file COPYING in the source
 | 
			
		||||
     distribution of Linux.
 | 
			
		||||
   </para>
 | 
			
		||||
  </legalnotice>
 | 
			
		||||
 </bookinfo>
 | 
			
		||||
 | 
			
		||||
<toc></toc>
 | 
			
		||||
 | 
			
		||||
  <chapter id="Basics">
 | 
			
		||||
     <title>Driver Basics</title>
 | 
			
		||||
     <sect1><title>Driver Entry and Exit points</title>
 | 
			
		||||
!Iinclude/linux/init.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Atomic and pointer manipulation</title>
 | 
			
		||||
!Iarch/x86/include/asm/atomic_32.h
 | 
			
		||||
!Iarch/x86/include/asm/unaligned.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Delaying, scheduling, and timer routines</title>
 | 
			
		||||
!Iinclude/linux/sched.h
 | 
			
		||||
!Ekernel/sched.c
 | 
			
		||||
!Ekernel/timer.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>High-resolution timers</title>
 | 
			
		||||
!Iinclude/linux/ktime.h
 | 
			
		||||
!Iinclude/linux/hrtimer.h
 | 
			
		||||
!Ekernel/hrtimer.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Workqueues and Kevents</title>
 | 
			
		||||
!Ekernel/workqueue.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Internal Functions</title>
 | 
			
		||||
!Ikernel/exit.c
 | 
			
		||||
!Ikernel/signal.c
 | 
			
		||||
!Iinclude/linux/kthread.h
 | 
			
		||||
!Ekernel/kthread.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Kernel objects manipulation</title>
 | 
			
		||||
<!--
 | 
			
		||||
X!Iinclude/linux/kobject.h
 | 
			
		||||
-->
 | 
			
		||||
!Elib/kobject.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Kernel utility functions</title>
 | 
			
		||||
!Iinclude/linux/kernel.h
 | 
			
		||||
!Ekernel/printk.c
 | 
			
		||||
!Ekernel/panic.c
 | 
			
		||||
!Ekernel/sys.c
 | 
			
		||||
!Ekernel/rcupdate.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Device Resource Management</title>
 | 
			
		||||
!Edrivers/base/devres.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="devdrivers">
 | 
			
		||||
     <title>Device drivers infrastructure</title>
 | 
			
		||||
     <sect1><title>Device Drivers Base</title>
 | 
			
		||||
<!--
 | 
			
		||||
X!Iinclude/linux/device.h
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/driver.c
 | 
			
		||||
!Edrivers/base/core.c
 | 
			
		||||
!Edrivers/base/class.c
 | 
			
		||||
!Edrivers/base/firmware_class.c
 | 
			
		||||
!Edrivers/base/transport_class.c
 | 
			
		||||
<!-- Cannot be included, because
 | 
			
		||||
     attribute_container_add_class_device_adapter
 | 
			
		||||
 and attribute_container_classdev_to_container
 | 
			
		||||
     exceed allowed 44 characters maximum
 | 
			
		||||
X!Edrivers/base/attribute_container.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/sys.c
 | 
			
		||||
<!--
 | 
			
		||||
X!Edrivers/base/interface.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/platform.c
 | 
			
		||||
!Edrivers/base/bus.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device Drivers Power Management</title>
 | 
			
		||||
!Edrivers/base/power/main.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device Drivers ACPI Support</title>
 | 
			
		||||
<!-- Internal functions only
 | 
			
		||||
X!Edrivers/acpi/sleep/main.c
 | 
			
		||||
X!Edrivers/acpi/sleep/wakeup.c
 | 
			
		||||
X!Edrivers/acpi/motherboard.c
 | 
			
		||||
X!Edrivers/acpi/bus.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/acpi/scan.c
 | 
			
		||||
!Idrivers/acpi/scan.c
 | 
			
		||||
<!-- No correct structured comments
 | 
			
		||||
X!Edrivers/acpi/pci_bind.c
 | 
			
		||||
-->
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device drivers PnP support</title>
 | 
			
		||||
!Idrivers/pnp/core.c
 | 
			
		||||
<!-- No correct structured comments
 | 
			
		||||
X!Edrivers/pnp/system.c
 | 
			
		||||
 -->
 | 
			
		||||
!Edrivers/pnp/card.c
 | 
			
		||||
!Idrivers/pnp/driver.c
 | 
			
		||||
!Edrivers/pnp/manager.c
 | 
			
		||||
!Edrivers/pnp/support.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Userspace IO devices</title>
 | 
			
		||||
!Edrivers/uio/uio.c
 | 
			
		||||
!Iinclude/linux/uio_driver.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="parportdev">
 | 
			
		||||
     <title>Parallel Port Devices</title>
 | 
			
		||||
!Iinclude/linux/parport.h
 | 
			
		||||
!Edrivers/parport/ieee1284.c
 | 
			
		||||
!Edrivers/parport/share.c
 | 
			
		||||
!Idrivers/parport/daisy.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="message_devices">
 | 
			
		||||
	<title>Message-based devices</title>
 | 
			
		||||
     <sect1><title>Fusion message devices</title>
 | 
			
		||||
!Edrivers/message/fusion/mptbase.c
 | 
			
		||||
!Idrivers/message/fusion/mptbase.c
 | 
			
		||||
!Edrivers/message/fusion/mptscsih.c
 | 
			
		||||
!Idrivers/message/fusion/mptscsih.c
 | 
			
		||||
!Idrivers/message/fusion/mptctl.c
 | 
			
		||||
!Idrivers/message/fusion/mptspi.c
 | 
			
		||||
!Idrivers/message/fusion/mptfc.c
 | 
			
		||||
!Idrivers/message/fusion/mptlan.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>I2O message devices</title>
 | 
			
		||||
!Iinclude/linux/i2o.h
 | 
			
		||||
!Idrivers/message/i2o/core.h
 | 
			
		||||
!Edrivers/message/i2o/iop.c
 | 
			
		||||
!Idrivers/message/i2o/iop.c
 | 
			
		||||
!Idrivers/message/i2o/config-osm.c
 | 
			
		||||
!Edrivers/message/i2o/exec-osm.c
 | 
			
		||||
!Idrivers/message/i2o/exec-osm.c
 | 
			
		||||
!Idrivers/message/i2o/bus-osm.c
 | 
			
		||||
!Edrivers/message/i2o/device.c
 | 
			
		||||
!Idrivers/message/i2o/device.c
 | 
			
		||||
!Idrivers/message/i2o/driver.c
 | 
			
		||||
!Idrivers/message/i2o/pci.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_block.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_scsi.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_proc.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="snddev">
 | 
			
		||||
     <title>Sound Devices</title>
 | 
			
		||||
!Iinclude/sound/core.h
 | 
			
		||||
!Esound/sound_core.c
 | 
			
		||||
!Iinclude/sound/pcm.h
 | 
			
		||||
!Esound/core/pcm.c
 | 
			
		||||
!Esound/core/device.c
 | 
			
		||||
!Esound/core/info.c
 | 
			
		||||
!Esound/core/rawmidi.c
 | 
			
		||||
!Esound/core/sound.c
 | 
			
		||||
!Esound/core/memory.c
 | 
			
		||||
!Esound/core/pcm_memory.c
 | 
			
		||||
!Esound/core/init.c
 | 
			
		||||
!Esound/core/isadma.c
 | 
			
		||||
!Esound/core/control.c
 | 
			
		||||
!Esound/core/pcm_lib.c
 | 
			
		||||
!Esound/core/hwdep.c
 | 
			
		||||
!Esound/core/pcm_native.c
 | 
			
		||||
!Esound/core/memalloc.c
 | 
			
		||||
<!-- FIXME: Removed for now since no structured comments in source
 | 
			
		||||
X!Isound/sound_firmware.c
 | 
			
		||||
-->
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="uart16x50">
 | 
			
		||||
     <title>16x50 UART Driver</title>
 | 
			
		||||
!Iinclude/linux/serial_core.h
 | 
			
		||||
!Edrivers/serial/serial_core.c
 | 
			
		||||
!Edrivers/serial/8250.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="fbdev">
 | 
			
		||||
     <title>Frame Buffer Library</title>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The frame buffer drivers depend heavily on four data structures.
 | 
			
		||||
       These structures are declared in include/linux/fb.h.  They are
 | 
			
		||||
       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs.
 | 
			
		||||
       The last three can be made available to and from userland.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       fb_info defines the current state of a particular video card.
 | 
			
		||||
       Inside fb_info, there exists a fb_ops structure which is a
 | 
			
		||||
       collection of needed functions to make fbdev and fbcon work.
 | 
			
		||||
       fb_info is only visible to the kernel.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       fb_var_screeninfo is used to describe the features of a video card
 | 
			
		||||
       that are user defined.  With fb_var_screeninfo, things such as
 | 
			
		||||
       depth and the resolution may be defined.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The next structure is fb_fix_screeninfo. This defines the
 | 
			
		||||
       properties of a card that are created when a mode is set and can't
 | 
			
		||||
       be changed otherwise.  A good example of this is the start of the
 | 
			
		||||
       frame buffer memory.  This "locks" the address of the frame buffer
 | 
			
		||||
       memory, so that it cannot be changed or moved.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The last structure is fb_monospecs. In the old API, there was
 | 
			
		||||
       little importance for fb_monospecs. This allowed for forbidden things
 | 
			
		||||
       such as setting a mode of 800x600 on a fix frequency monitor. With
 | 
			
		||||
       the new API, fb_monospecs prevents such things, and if used
 | 
			
		||||
       correctly, can prevent a monitor from being cooked.  fb_monospecs
 | 
			
		||||
       will not be useful until kernels 2.5.x.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Frame Buffer Memory</title>
 | 
			
		||||
!Edrivers/video/fbmem.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
<!--
 | 
			
		||||
     <sect1><title>Frame Buffer Console</title>
 | 
			
		||||
X!Edrivers/video/console/fbcon.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
-->
 | 
			
		||||
     <sect1><title>Frame Buffer Colormap</title>
 | 
			
		||||
!Edrivers/video/fbcmap.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
<!-- FIXME:
 | 
			
		||||
  drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
 | 
			
		||||
  out until somebody adds docs.  KAO
 | 
			
		||||
     <sect1><title>Frame Buffer Generic Functions</title>
 | 
			
		||||
X!Idrivers/video/fbgen.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
KAO -->
 | 
			
		||||
     <sect1><title>Frame Buffer Video Mode Database</title>
 | 
			
		||||
!Idrivers/video/modedb.c
 | 
			
		||||
!Edrivers/video/modedb.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
 | 
			
		||||
!Edrivers/video/macmodes.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Frame Buffer Fonts</title>
 | 
			
		||||
        <para>
 | 
			
		||||
           Refer to the file drivers/video/console/fonts.c for more information.
 | 
			
		||||
        </para>
 | 
			
		||||
<!-- FIXME: Removed for now since no structured comments in source
 | 
			
		||||
X!Idrivers/video/console/fonts.c
 | 
			
		||||
-->
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="input_subsystem">
 | 
			
		||||
     <title>Input Subsystem</title>
 | 
			
		||||
!Iinclude/linux/input.h
 | 
			
		||||
!Edrivers/input/input.c
 | 
			
		||||
!Edrivers/input/ff-core.c
 | 
			
		||||
!Edrivers/input/ff-memless.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="spi">
 | 
			
		||||
      <title>Serial Peripheral Interface (SPI)</title>
 | 
			
		||||
  <para>
 | 
			
		||||
	SPI is the "Serial Peripheral Interface", widely used with
 | 
			
		||||
	embedded systems because it is a simple and efficient
 | 
			
		||||
	interface:  basically a multiplexed shift register.
 | 
			
		||||
	Its three signal wires hold a clock (SCK, often in the range
 | 
			
		||||
	of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
 | 
			
		||||
	a "Master In, Slave Out" (MISO) data line.
 | 
			
		||||
	SPI is a full duplex protocol; for each bit shifted out the
 | 
			
		||||
	MOSI line (one per clock) another is shifted in on the MISO line.
 | 
			
		||||
	Those bits are assembled into words of various sizes on the
 | 
			
		||||
	way to and from system memory.
 | 
			
		||||
	An additional chipselect line is usually active-low (nCS);
 | 
			
		||||
	four signals are normally used for each peripheral, plus
 | 
			
		||||
	sometimes an interrupt.
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The SPI bus facilities listed here provide a generalized
 | 
			
		||||
	interface to declare SPI busses and devices, manage them
 | 
			
		||||
	according to the standard Linux driver model, and perform
 | 
			
		||||
	input/output operations.
 | 
			
		||||
	At this time, only "master" side interfaces are supported,
 | 
			
		||||
	where Linux talks to SPI peripherals and does not implement
 | 
			
		||||
	such a peripheral itself.
 | 
			
		||||
	(Interfaces to support implementing SPI slaves would
 | 
			
		||||
	necessarily look different.)
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The programming interface is structured around two kinds of driver,
 | 
			
		||||
	and two kinds of device.
 | 
			
		||||
	A "Controller Driver" abstracts the controller hardware, which may
 | 
			
		||||
	be as simple as a set of GPIO pins or as complex as a pair of FIFOs
 | 
			
		||||
	connected to dual DMA engines on the other side of the SPI shift
 | 
			
		||||
	register (maximizing throughput).  Such drivers bridge between
 | 
			
		||||
	whatever bus they sit on (often the platform bus) and SPI, and
 | 
			
		||||
	expose the SPI side of their device as a
 | 
			
		||||
	<structname>struct spi_master</structname>.
 | 
			
		||||
	SPI devices are children of that master, represented as a
 | 
			
		||||
	<structname>struct spi_device</structname> and manufactured from
 | 
			
		||||
	<structname>struct spi_board_info</structname> descriptors which
 | 
			
		||||
	are usually provided by board-specific initialization code.
 | 
			
		||||
	A <structname>struct spi_driver</structname> is called a
 | 
			
		||||
	"Protocol Driver", and is bound to a spi_device using normal
 | 
			
		||||
	driver model calls.
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The I/O model is a set of queued messages.  Protocol drivers
 | 
			
		||||
	submit one or more <structname>struct spi_message</structname>
 | 
			
		||||
	objects, which are processed and completed asynchronously.
 | 
			
		||||
	(There are synchronous wrappers, however.)  Messages are
 | 
			
		||||
	built from one or more <structname>struct spi_transfer</structname>
 | 
			
		||||
	objects, each of which wraps a full duplex SPI transfer.
 | 
			
		||||
	A variety of protocol tweaking options are needed, because
 | 
			
		||||
	different chips adopt very different policies for how they
 | 
			
		||||
	use the bits transferred with SPI.
 | 
			
		||||
  </para>
 | 
			
		||||
!Iinclude/linux/spi/spi.h
 | 
			
		||||
!Fdrivers/spi/spi.c spi_register_board_info
 | 
			
		||||
!Edrivers/spi/spi.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="i2c">
 | 
			
		||||
     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	I<superscript>2</superscript>C (or without fancy typography, "I2C")
 | 
			
		||||
	is an acronym for the "Inter-IC" bus, a simple bus protocol which is
 | 
			
		||||
	widely used where low data rate communications suffice.
 | 
			
		||||
	Since it's also a licensed trademark, some vendors use another
 | 
			
		||||
	name (such as "Two-Wire Interface", TWI) for the same bus.
 | 
			
		||||
	I2C only needs two signals (SCL for clock, SDA for data), conserving
 | 
			
		||||
	board real estate and minimizing signal quality issues.
 | 
			
		||||
	Most I2C devices use seven bit addresses, and bus speeds of up
 | 
			
		||||
	to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
 | 
			
		||||
	found wide use.
 | 
			
		||||
	I2C is a multi-master bus; open drain signaling is used to
 | 
			
		||||
	arbitrate between masters, as well as to handshake and to
 | 
			
		||||
	synchronize clocks from slower clients.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	The Linux I2C programming interfaces support only the master
 | 
			
		||||
	side of bus interactions, not the slave side.
 | 
			
		||||
	The programming interface is structured around two kinds of driver,
 | 
			
		||||
	and two kinds of device.
 | 
			
		||||
	An I2C "Adapter Driver" abstracts the controller hardware; it binds
 | 
			
		||||
	to a physical device (perhaps a PCI device or platform_device) and
 | 
			
		||||
	exposes a <structname>struct i2c_adapter</structname> representing
 | 
			
		||||
	each I2C bus segment it manages.
 | 
			
		||||
	On each I2C bus segment will be I2C devices represented by a
 | 
			
		||||
	<structname>struct i2c_client</structname>.  Those devices will
 | 
			
		||||
	be bound to a <structname>struct i2c_driver</structname>,
 | 
			
		||||
	which should follow the standard Linux driver model.
 | 
			
		||||
	(At this writing, a legacy model is more widely used.)
 | 
			
		||||
	There are functions to perform various I2C protocol operations; at
 | 
			
		||||
	this writing all such functions are usable only from task context.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
 | 
			
		||||
	systems are also I2C conformant.  The electrical constraints are
 | 
			
		||||
	tighter for SMBus, and it standardizes particular protocol messages
 | 
			
		||||
	and idioms.  Controllers that support I2C can also support most
 | 
			
		||||
	SMBus operations, but SMBus controllers don't support all the protocol
 | 
			
		||||
	options that an I2C controller will.
 | 
			
		||||
	There are functions to perform various SMBus protocol operations,
 | 
			
		||||
	either using I2C primitives or by issuing SMBus commands to
 | 
			
		||||
	i2c_adapter devices which don't support those I2C operations.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
!Iinclude/linux/i2c.h
 | 
			
		||||
!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
 | 
			
		||||
!Edrivers/i2c/i2c-core.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
</book>
 | 
			
		||||
| 
						 | 
				
			
			@ -38,58 +38,6 @@
 | 
			
		|||
 | 
			
		||||
<toc></toc>
 | 
			
		||||
 | 
			
		||||
  <chapter id="Basics">
 | 
			
		||||
     <title>Driver Basics</title>
 | 
			
		||||
     <sect1><title>Driver Entry and Exit points</title>
 | 
			
		||||
!Iinclude/linux/init.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Atomic and pointer manipulation</title>
 | 
			
		||||
!Iarch/x86/include/asm/atomic_32.h
 | 
			
		||||
!Iarch/x86/include/asm/unaligned.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Delaying, scheduling, and timer routines</title>
 | 
			
		||||
!Iinclude/linux/sched.h
 | 
			
		||||
!Ekernel/sched.c
 | 
			
		||||
!Ekernel/timer.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>High-resolution timers</title>
 | 
			
		||||
!Iinclude/linux/ktime.h
 | 
			
		||||
!Iinclude/linux/hrtimer.h
 | 
			
		||||
!Ekernel/hrtimer.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Workqueues and Kevents</title>
 | 
			
		||||
!Ekernel/workqueue.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Internal Functions</title>
 | 
			
		||||
!Ikernel/exit.c
 | 
			
		||||
!Ikernel/signal.c
 | 
			
		||||
!Iinclude/linux/kthread.h
 | 
			
		||||
!Ekernel/kthread.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Kernel objects manipulation</title>
 | 
			
		||||
<!--
 | 
			
		||||
X!Iinclude/linux/kobject.h
 | 
			
		||||
-->
 | 
			
		||||
!Elib/kobject.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Kernel utility functions</title>
 | 
			
		||||
!Iinclude/linux/kernel.h
 | 
			
		||||
!Ekernel/printk.c
 | 
			
		||||
!Ekernel/panic.c
 | 
			
		||||
!Ekernel/sys.c
 | 
			
		||||
!Ekernel/rcupdate.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Device Resource Management</title>
 | 
			
		||||
!Edrivers/base/devres.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="adt">
 | 
			
		||||
     <title>Data Types</title>
 | 
			
		||||
     <sect1><title>Doubly Linked Lists</title>
 | 
			
		||||
| 
						 | 
				
			
			@ -298,62 +246,6 @@ X!Earch/x86/kernel/mca_32.c
 | 
			
		|||
!Ikernel/acct.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="devdrivers">
 | 
			
		||||
     <title>Device drivers infrastructure</title>
 | 
			
		||||
     <sect1><title>Device Drivers Base</title>
 | 
			
		||||
<!--
 | 
			
		||||
X!Iinclude/linux/device.h
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/driver.c
 | 
			
		||||
!Edrivers/base/core.c
 | 
			
		||||
!Edrivers/base/class.c
 | 
			
		||||
!Edrivers/base/firmware_class.c
 | 
			
		||||
!Edrivers/base/transport_class.c
 | 
			
		||||
<!-- Cannot be included, because
 | 
			
		||||
     attribute_container_add_class_device_adapter
 | 
			
		||||
 and attribute_container_classdev_to_container
 | 
			
		||||
     exceed allowed 44 characters maximum
 | 
			
		||||
X!Edrivers/base/attribute_container.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/sys.c
 | 
			
		||||
<!--
 | 
			
		||||
X!Edrivers/base/interface.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/base/platform.c
 | 
			
		||||
!Edrivers/base/bus.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device Drivers Power Management</title>
 | 
			
		||||
!Edrivers/base/power/main.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device Drivers ACPI Support</title>
 | 
			
		||||
<!-- Internal functions only
 | 
			
		||||
X!Edrivers/acpi/sleep/main.c
 | 
			
		||||
X!Edrivers/acpi/sleep/wakeup.c
 | 
			
		||||
X!Edrivers/acpi/motherboard.c
 | 
			
		||||
X!Edrivers/acpi/bus.c
 | 
			
		||||
-->
 | 
			
		||||
!Edrivers/acpi/scan.c
 | 
			
		||||
!Idrivers/acpi/scan.c
 | 
			
		||||
<!-- No correct structured comments
 | 
			
		||||
X!Edrivers/acpi/pci_bind.c
 | 
			
		||||
-->
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Device drivers PnP support</title>
 | 
			
		||||
!Idrivers/pnp/core.c
 | 
			
		||||
<!-- No correct structured comments
 | 
			
		||||
X!Edrivers/pnp/system.c
 | 
			
		||||
 -->
 | 
			
		||||
!Edrivers/pnp/card.c
 | 
			
		||||
!Idrivers/pnp/driver.c
 | 
			
		||||
!Edrivers/pnp/manager.c
 | 
			
		||||
!Edrivers/pnp/support.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Userspace IO devices</title>
 | 
			
		||||
!Edrivers/uio/uio.c
 | 
			
		||||
!Iinclude/linux/uio_driver.h
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="blkdev">
 | 
			
		||||
     <title>Block Devices</title>
 | 
			
		||||
!Eblock/blk-core.c
 | 
			
		||||
| 
						 | 
				
			
			@ -381,275 +273,6 @@ X!Edrivers/pnp/system.c
 | 
			
		|||
!Edrivers/char/misc.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="parportdev">
 | 
			
		||||
     <title>Parallel Port Devices</title>
 | 
			
		||||
!Iinclude/linux/parport.h
 | 
			
		||||
!Edrivers/parport/ieee1284.c
 | 
			
		||||
!Edrivers/parport/share.c
 | 
			
		||||
!Idrivers/parport/daisy.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="message_devices">
 | 
			
		||||
	<title>Message-based devices</title>
 | 
			
		||||
     <sect1><title>Fusion message devices</title>
 | 
			
		||||
!Edrivers/message/fusion/mptbase.c
 | 
			
		||||
!Idrivers/message/fusion/mptbase.c
 | 
			
		||||
!Edrivers/message/fusion/mptscsih.c
 | 
			
		||||
!Idrivers/message/fusion/mptscsih.c
 | 
			
		||||
!Idrivers/message/fusion/mptctl.c
 | 
			
		||||
!Idrivers/message/fusion/mptspi.c
 | 
			
		||||
!Idrivers/message/fusion/mptfc.c
 | 
			
		||||
!Idrivers/message/fusion/mptlan.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>I2O message devices</title>
 | 
			
		||||
!Iinclude/linux/i2o.h
 | 
			
		||||
!Idrivers/message/i2o/core.h
 | 
			
		||||
!Edrivers/message/i2o/iop.c
 | 
			
		||||
!Idrivers/message/i2o/iop.c
 | 
			
		||||
!Idrivers/message/i2o/config-osm.c
 | 
			
		||||
!Edrivers/message/i2o/exec-osm.c
 | 
			
		||||
!Idrivers/message/i2o/exec-osm.c
 | 
			
		||||
!Idrivers/message/i2o/bus-osm.c
 | 
			
		||||
!Edrivers/message/i2o/device.c
 | 
			
		||||
!Idrivers/message/i2o/device.c
 | 
			
		||||
!Idrivers/message/i2o/driver.c
 | 
			
		||||
!Idrivers/message/i2o/pci.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_block.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_scsi.c
 | 
			
		||||
!Idrivers/message/i2o/i2o_proc.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="snddev">
 | 
			
		||||
     <title>Sound Devices</title>
 | 
			
		||||
!Iinclude/sound/core.h
 | 
			
		||||
!Esound/sound_core.c
 | 
			
		||||
!Iinclude/sound/pcm.h
 | 
			
		||||
!Esound/core/pcm.c
 | 
			
		||||
!Esound/core/device.c
 | 
			
		||||
!Esound/core/info.c
 | 
			
		||||
!Esound/core/rawmidi.c
 | 
			
		||||
!Esound/core/sound.c
 | 
			
		||||
!Esound/core/memory.c
 | 
			
		||||
!Esound/core/pcm_memory.c
 | 
			
		||||
!Esound/core/init.c
 | 
			
		||||
!Esound/core/isadma.c
 | 
			
		||||
!Esound/core/control.c
 | 
			
		||||
!Esound/core/pcm_lib.c
 | 
			
		||||
!Esound/core/hwdep.c
 | 
			
		||||
!Esound/core/pcm_native.c
 | 
			
		||||
!Esound/core/memalloc.c
 | 
			
		||||
<!-- FIXME: Removed for now since no structured comments in source
 | 
			
		||||
X!Isound/sound_firmware.c
 | 
			
		||||
-->
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="uart16x50">
 | 
			
		||||
     <title>16x50 UART Driver</title>
 | 
			
		||||
!Iinclude/linux/serial_core.h
 | 
			
		||||
!Edrivers/serial/serial_core.c
 | 
			
		||||
!Edrivers/serial/8250.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="fbdev">
 | 
			
		||||
     <title>Frame Buffer Library</title>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The frame buffer drivers depend heavily on four data structures.  
 | 
			
		||||
       These structures are declared in include/linux/fb.h.  They are 
 | 
			
		||||
       fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs. 
 | 
			
		||||
       The last three can be made available to and from userland. 
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       fb_info defines the current state of a particular video card. 
 | 
			
		||||
       Inside fb_info, there exists a fb_ops structure which is a 
 | 
			
		||||
       collection of needed functions to make fbdev and fbcon work.
 | 
			
		||||
       fb_info is only visible to the kernel.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       fb_var_screeninfo is used to describe the features of a video card 
 | 
			
		||||
       that are user defined.  With fb_var_screeninfo, things such as
 | 
			
		||||
       depth and the resolution may be defined.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The next structure is fb_fix_screeninfo. This defines the 
 | 
			
		||||
       properties of a card that are created when a mode is set and can't 
 | 
			
		||||
       be changed otherwise.  A good example of this is the start of the 
 | 
			
		||||
       frame buffer memory.  This "locks" the address of the frame buffer
 | 
			
		||||
       memory, so that it cannot be changed or moved.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
       The last structure is fb_monospecs. In the old API, there was 
 | 
			
		||||
       little importance for fb_monospecs. This allowed for forbidden things 
 | 
			
		||||
       such as setting a mode of 800x600 on a fix frequency monitor. With 
 | 
			
		||||
       the new API, fb_monospecs prevents such things, and if used 
 | 
			
		||||
       correctly, can prevent a monitor from being cooked.  fb_monospecs
 | 
			
		||||
       will not be useful until kernels 2.5.x.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <sect1><title>Frame Buffer Memory</title>
 | 
			
		||||
!Edrivers/video/fbmem.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
<!--
 | 
			
		||||
     <sect1><title>Frame Buffer Console</title>
 | 
			
		||||
X!Edrivers/video/console/fbcon.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
-->
 | 
			
		||||
     <sect1><title>Frame Buffer Colormap</title>
 | 
			
		||||
!Edrivers/video/fbcmap.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
<!-- FIXME:
 | 
			
		||||
  drivers/video/fbgen.c has no docs, which stuffs up the sgml.  Comment
 | 
			
		||||
  out until somebody adds docs.  KAO
 | 
			
		||||
     <sect1><title>Frame Buffer Generic Functions</title>
 | 
			
		||||
X!Idrivers/video/fbgen.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
KAO -->
 | 
			
		||||
     <sect1><title>Frame Buffer Video Mode Database</title>
 | 
			
		||||
!Idrivers/video/modedb.c
 | 
			
		||||
!Edrivers/video/modedb.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
 | 
			
		||||
!Edrivers/video/macmodes.c
 | 
			
		||||
     </sect1>
 | 
			
		||||
     <sect1><title>Frame Buffer Fonts</title>
 | 
			
		||||
        <para>
 | 
			
		||||
           Refer to the file drivers/video/console/fonts.c for more information.
 | 
			
		||||
        </para>
 | 
			
		||||
<!-- FIXME: Removed for now since no structured comments in source
 | 
			
		||||
X!Idrivers/video/console/fonts.c
 | 
			
		||||
-->
 | 
			
		||||
     </sect1>
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="input_subsystem">
 | 
			
		||||
     <title>Input Subsystem</title>
 | 
			
		||||
!Iinclude/linux/input.h
 | 
			
		||||
!Edrivers/input/input.c
 | 
			
		||||
!Edrivers/input/ff-core.c
 | 
			
		||||
!Edrivers/input/ff-memless.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="spi">
 | 
			
		||||
      <title>Serial Peripheral Interface (SPI)</title>
 | 
			
		||||
  <para>
 | 
			
		||||
	SPI is the "Serial Peripheral Interface", widely used with
 | 
			
		||||
	embedded systems because it is a simple and efficient
 | 
			
		||||
	interface:  basically a multiplexed shift register.
 | 
			
		||||
	Its three signal wires hold a clock (SCK, often in the range
 | 
			
		||||
	of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
 | 
			
		||||
	a "Master In, Slave Out" (MISO) data line.
 | 
			
		||||
	SPI is a full duplex protocol; for each bit shifted out the
 | 
			
		||||
	MOSI line (one per clock) another is shifted in on the MISO line.
 | 
			
		||||
	Those bits are assembled into words of various sizes on the
 | 
			
		||||
	way to and from system memory.
 | 
			
		||||
	An additional chipselect line is usually active-low (nCS);
 | 
			
		||||
	four signals are normally used for each peripheral, plus
 | 
			
		||||
	sometimes an interrupt.
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The SPI bus facilities listed here provide a generalized
 | 
			
		||||
	interface to declare SPI busses and devices, manage them
 | 
			
		||||
	according to the standard Linux driver model, and perform
 | 
			
		||||
	input/output operations.
 | 
			
		||||
	At this time, only "master" side interfaces are supported,
 | 
			
		||||
	where Linux talks to SPI peripherals and does not implement
 | 
			
		||||
	such a peripheral itself.
 | 
			
		||||
	(Interfaces to support implementing SPI slaves would
 | 
			
		||||
	necessarily look different.)
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The programming interface is structured around two kinds of driver,
 | 
			
		||||
	and two kinds of device.
 | 
			
		||||
	A "Controller Driver" abstracts the controller hardware, which may
 | 
			
		||||
	be as simple as a set of GPIO pins or as complex as a pair of FIFOs
 | 
			
		||||
	connected to dual DMA engines on the other side of the SPI shift
 | 
			
		||||
	register (maximizing throughput).  Such drivers bridge between
 | 
			
		||||
	whatever bus they sit on (often the platform bus) and SPI, and
 | 
			
		||||
	expose the SPI side of their device as a
 | 
			
		||||
	<structname>struct spi_master</structname>.
 | 
			
		||||
	SPI devices are children of that master, represented as a
 | 
			
		||||
	<structname>struct spi_device</structname> and manufactured from
 | 
			
		||||
	<structname>struct spi_board_info</structname> descriptors which
 | 
			
		||||
	are usually provided by board-specific initialization code.
 | 
			
		||||
	A <structname>struct spi_driver</structname> is called a
 | 
			
		||||
	"Protocol Driver", and is bound to a spi_device using normal
 | 
			
		||||
	driver model calls.
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The I/O model is a set of queued messages.  Protocol drivers
 | 
			
		||||
	submit one or more <structname>struct spi_message</structname>
 | 
			
		||||
	objects, which are processed and completed asynchronously.
 | 
			
		||||
	(There are synchronous wrappers, however.)  Messages are
 | 
			
		||||
	built from one or more <structname>struct spi_transfer</structname>
 | 
			
		||||
	objects, each of which wraps a full duplex SPI transfer.
 | 
			
		||||
	A variety of protocol tweaking options are needed, because
 | 
			
		||||
	different chips adopt very different policies for how they
 | 
			
		||||
	use the bits transferred with SPI.
 | 
			
		||||
  </para>
 | 
			
		||||
!Iinclude/linux/spi/spi.h
 | 
			
		||||
!Fdrivers/spi/spi.c spi_register_board_info
 | 
			
		||||
!Edrivers/spi/spi.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="i2c">
 | 
			
		||||
     <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	I<superscript>2</superscript>C (or without fancy typography, "I2C")
 | 
			
		||||
	is an acronym for the "Inter-IC" bus, a simple bus protocol which is
 | 
			
		||||
	widely used where low data rate communications suffice.
 | 
			
		||||
	Since it's also a licensed trademark, some vendors use another
 | 
			
		||||
	name (such as "Two-Wire Interface", TWI) for the same bus.
 | 
			
		||||
	I2C only needs two signals (SCL for clock, SDA for data), conserving
 | 
			
		||||
	board real estate and minimizing signal quality issues.
 | 
			
		||||
	Most I2C devices use seven bit addresses, and bus speeds of up
 | 
			
		||||
	to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
 | 
			
		||||
	found wide use.
 | 
			
		||||
	I2C is a multi-master bus; open drain signaling is used to
 | 
			
		||||
	arbitrate between masters, as well as to handshake and to
 | 
			
		||||
	synchronize clocks from slower clients.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	The Linux I2C programming interfaces support only the master
 | 
			
		||||
	side of bus interactions, not the slave side.
 | 
			
		||||
	The programming interface is structured around two kinds of driver,
 | 
			
		||||
	and two kinds of device.
 | 
			
		||||
	An I2C "Adapter Driver" abstracts the controller hardware; it binds
 | 
			
		||||
	to a physical device (perhaps a PCI device or platform_device) and
 | 
			
		||||
	exposes a <structname>struct i2c_adapter</structname> representing
 | 
			
		||||
	each I2C bus segment it manages.
 | 
			
		||||
	On each I2C bus segment will be I2C devices represented by a
 | 
			
		||||
	<structname>struct i2c_client</structname>.  Those devices will
 | 
			
		||||
	be bound to a <structname>struct i2c_driver</structname>,
 | 
			
		||||
	which should follow the standard Linux driver model.
 | 
			
		||||
	(At this writing, a legacy model is more widely used.)
 | 
			
		||||
	There are functions to perform various I2C protocol operations; at
 | 
			
		||||
	this writing all such functions are usable only from task context.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
     <para>
 | 
			
		||||
	The System Management Bus (SMBus) is a sibling protocol.  Most SMBus
 | 
			
		||||
	systems are also I2C conformant.  The electrical constraints are
 | 
			
		||||
	tighter for SMBus, and it standardizes particular protocol messages
 | 
			
		||||
	and idioms.  Controllers that support I2C can also support most
 | 
			
		||||
	SMBus operations, but SMBus controllers don't support all the protocol
 | 
			
		||||
	options that an I2C controller will.
 | 
			
		||||
	There are functions to perform various SMBus protocol operations,
 | 
			
		||||
	either using I2C primitives or by issuing SMBus commands to
 | 
			
		||||
	i2c_adapter devices which don't support those I2C operations.
 | 
			
		||||
     </para>
 | 
			
		||||
 | 
			
		||||
!Iinclude/linux/i2c.h
 | 
			
		||||
!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
 | 
			
		||||
!Edrivers/i2c/i2c-core.c
 | 
			
		||||
  </chapter>
 | 
			
		||||
 | 
			
		||||
  <chapter id="clk">
 | 
			
		||||
     <title>Clock Framework</title>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,7 +142,7 @@ into the rest of the kernel, none in performance critical paths:
 | 
			
		|||
 - in fork and exit, to attach and detach a task from its cpuset.
 | 
			
		||||
 - in sched_setaffinity, to mask the requested CPUs by what's
 | 
			
		||||
   allowed in that tasks cpuset.
 | 
			
		||||
 - in sched.c migrate_all_tasks(), to keep migrating tasks within
 | 
			
		||||
 - in sched.c migrate_live_tasks(), to keep migrating tasks within
 | 
			
		||||
   the CPUs allowed by their cpuset, if possible.
 | 
			
		||||
 - in the mbind and set_mempolicy system calls, to mask the requested
 | 
			
		||||
   Memory Nodes by what's allowed in that tasks cpuset.
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +175,10 @@ files describing that cpuset:
 | 
			
		|||
 - mem_exclusive flag: is memory placement exclusive?
 | 
			
		||||
 - mem_hardwall flag:  is memory allocation hardwalled
 | 
			
		||||
 - memory_pressure: measure of how much paging pressure in cpuset
 | 
			
		||||
 - memory_spread_page flag: if set, spread page cache evenly on allowed nodes
 | 
			
		||||
 - memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
 | 
			
		||||
 - sched_load_balance flag: if set, load balance within CPUs on that cpuset
 | 
			
		||||
 - sched_relax_domain_level: the searching range when migrating tasks
 | 
			
		||||
 | 
			
		||||
In addition, the root cpuset only has the following file:
 | 
			
		||||
 - memory_pressure_enabled flag: compute memory_pressure?
 | 
			
		||||
| 
						 | 
				
			
			@ -252,7 +256,7 @@ is causing.
 | 
			
		|||
 | 
			
		||||
This is useful both on tightly managed systems running a wide mix of
 | 
			
		||||
submitted jobs, which may choose to terminate or re-prioritize jobs that
 | 
			
		||||
are trying to use more memory than allowed on the nodes assigned them,
 | 
			
		||||
are trying to use more memory than allowed on the nodes assigned to them,
 | 
			
		||||
and with tightly coupled, long running, massively parallel scientific
 | 
			
		||||
computing jobs that will dramatically fail to meet required performance
 | 
			
		||||
goals if they start to use more memory than allowed to them.
 | 
			
		||||
| 
						 | 
				
			
			@ -485,17 +489,22 @@ of CPUs allowed to a cpuset having 'sched_load_balance' enabled.
 | 
			
		|||
The internal kernel cpuset to scheduler interface passes from the
 | 
			
		||||
cpuset code to the scheduler code a partition of the load balanced
 | 
			
		||||
CPUs in the system. This partition is a set of subsets (represented
 | 
			
		||||
as an array of cpumask_t) of CPUs, pairwise disjoint, that cover all
 | 
			
		||||
the CPUs that must be load balanced.
 | 
			
		||||
as an array of struct cpumask) of CPUs, pairwise disjoint, that cover
 | 
			
		||||
all the CPUs that must be load balanced.
 | 
			
		||||
 | 
			
		||||
Whenever the 'sched_load_balance' flag changes, or CPUs come or go
 | 
			
		||||
from a cpuset with this flag enabled, or a cpuset with this flag
 | 
			
		||||
enabled is removed, the cpuset code builds a new such partition and
 | 
			
		||||
passes it to the scheduler sched domain setup code, to have the sched
 | 
			
		||||
domains rebuilt as necessary.
 | 
			
		||||
The cpuset code builds a new such partition and passes it to the
 | 
			
		||||
scheduler sched domain setup code, to have the sched domains rebuilt
 | 
			
		||||
as necessary, whenever:
 | 
			
		||||
 - the 'sched_load_balance' flag of a cpuset with non-empty CPUs changes,
 | 
			
		||||
 - or CPUs come or go from a cpuset with this flag enabled,
 | 
			
		||||
 - or 'sched_relax_domain_level' value of a cpuset with non-empty CPUs
 | 
			
		||||
   and with this flag enabled changes,
 | 
			
		||||
 - or a cpuset with non-empty CPUs and with this flag enabled is removed,
 | 
			
		||||
 - or a cpu is offlined/onlined.
 | 
			
		||||
 | 
			
		||||
This partition exactly defines what sched domains the scheduler should
 | 
			
		||||
setup - one sched domain for each element (cpumask_t) in the partition.
 | 
			
		||||
setup - one sched domain for each element (struct cpumask) in the
 | 
			
		||||
partition.
 | 
			
		||||
 | 
			
		||||
The scheduler remembers the currently active sched domain partitions.
 | 
			
		||||
When the scheduler routine partition_sched_domains() is invoked from
 | 
			
		||||
| 
						 | 
				
			
			@ -559,7 +568,7 @@ domain, the largest value among those is used.  Be careful, if one
 | 
			
		|||
requests 0 and others are -1 then 0 is used.
 | 
			
		||||
 | 
			
		||||
Note that modifying this file will have both good and bad effects,
 | 
			
		||||
and whether it is acceptable or not will be depend on your situation.
 | 
			
		||||
and whether it is acceptable or not depends on your situation.
 | 
			
		||||
Don't modify this file if you are not sure.
 | 
			
		||||
 | 
			
		||||
If your situation is:
 | 
			
		||||
| 
						 | 
				
			
			@ -600,19 +609,15 @@ to allocate a page of memory for that task.
 | 
			
		|||
 | 
			
		||||
If a cpuset has its 'cpus' modified, then each task in that cpuset
 | 
			
		||||
will have its allowed CPU placement changed immediately.  Similarly,
 | 
			
		||||
if a tasks pid is written to a cpusets 'tasks' file, in either its
 | 
			
		||||
current cpuset or another cpuset, then its allowed CPU placement is
 | 
			
		||||
changed immediately.  If such a task had been bound to some subset
 | 
			
		||||
of its cpuset using the sched_setaffinity() call, the task will be
 | 
			
		||||
allowed to run on any CPU allowed in its new cpuset, negating the
 | 
			
		||||
affect of the prior sched_setaffinity() call.
 | 
			
		||||
if a tasks pid is written to another cpusets 'tasks' file, then its
 | 
			
		||||
allowed CPU placement is changed immediately.  If such a task had been
 | 
			
		||||
bound to some subset of its cpuset using the sched_setaffinity() call,
 | 
			
		||||
the task will be allowed to run on any CPU allowed in its new cpuset,
 | 
			
		||||
negating the effect of the prior sched_setaffinity() call.
 | 
			
		||||
 | 
			
		||||
In summary, the memory placement of a task whose cpuset is changed is
 | 
			
		||||
updated by the kernel, on the next allocation of a page for that task,
 | 
			
		||||
but the processor placement is not updated, until that tasks pid is
 | 
			
		||||
rewritten to the 'tasks' file of its cpuset.  This is done to avoid
 | 
			
		||||
impacting the scheduler code in the kernel with a check for changes
 | 
			
		||||
in a tasks processor placement.
 | 
			
		||||
and the processor placement is updated immediately.
 | 
			
		||||
 | 
			
		||||
Normally, once a page is allocated (given a physical page
 | 
			
		||||
of main memory) then that page stays on whatever node it
 | 
			
		||||
| 
						 | 
				
			
			@ -681,10 +686,14 @@ and then start a subshell 'sh' in that cpuset:
 | 
			
		|||
  # The next line should display '/Charlie'
 | 
			
		||||
  cat /proc/self/cpuset
 | 
			
		||||
 | 
			
		||||
In the future, a C library interface to cpusets will likely be
 | 
			
		||||
available.  For now, the only way to query or modify cpusets is
 | 
			
		||||
via the cpuset file system, using the various cd, mkdir, echo, cat,
 | 
			
		||||
rmdir commands from the shell, or their equivalent from C.
 | 
			
		||||
There are ways to query or modify cpusets:
 | 
			
		||||
 - via the cpuset file system directly, using the various cd, mkdir, echo,
 | 
			
		||||
   cat, rmdir commands from the shell, or their equivalent from C.
 | 
			
		||||
 - via the C library libcpuset.
 | 
			
		||||
 - via the C library libcgroup.
 | 
			
		||||
   (http://sourceforge.net/proects/libcg/)
 | 
			
		||||
 - via the python application cset.
 | 
			
		||||
   (http://developer.novell.com/wiki/index.php/Cpuset)
 | 
			
		||||
 | 
			
		||||
The sched_setaffinity calls can also be done at the shell prompt using
 | 
			
		||||
SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
 | 
			
		||||
| 
						 | 
				
			
			@ -756,7 +765,7 @@ mount -t cpuset X /dev/cpuset
 | 
			
		|||
 | 
			
		||||
is equivalent to
 | 
			
		||||
 | 
			
		||||
mount -t cgroup -ocpuset X /dev/cpuset
 | 
			
		||||
mount -t cgroup -ocpuset,noprefix X /dev/cpuset
 | 
			
		||||
echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
 | 
			
		||||
 | 
			
		||||
2.2 Adding/removing cpus
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,8 +128,10 @@ Attributes
 | 
			
		|||
~~~~~~~~~~
 | 
			
		||||
struct device_attribute {
 | 
			
		||||
	struct attribute	attr;
 | 
			
		||||
        ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
 | 
			
		||||
        ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
 | 
			
		||||
	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			char *buf);
 | 
			
		||||
	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			 const char *buf, size_t count);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Attributes of devices can be exported via drivers using a simple
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,8 +2,10 @@
 | 
			
		|||
sysfs - _The_ filesystem for exporting kernel objects. 
 | 
			
		||||
 | 
			
		||||
Patrick Mochel	<mochel@osdl.org>
 | 
			
		||||
Mike Murphy <mamurph@cs.clemson.edu>
 | 
			
		||||
 | 
			
		||||
10 January 2003
 | 
			
		||||
Revised:    22 February 2009
 | 
			
		||||
Original:   10 January 2003
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
What it is:
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +66,13 @@ An attribute definition is simply:
 | 
			
		|||
 | 
			
		||||
struct attribute {
 | 
			
		||||
        char                    * name;
 | 
			
		||||
        struct module		*owner;
 | 
			
		||||
        mode_t                  mode;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int sysfs_create_file(struct kobject * kobj, struct attribute * attr);
 | 
			
		||||
void sysfs_remove_file(struct kobject * kobj, struct attribute * attr);
 | 
			
		||||
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
 | 
			
		||||
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
A bare attribute contains no means to read or write the value of the
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +84,10 @@ For example, the driver model defines struct device_attribute like:
 | 
			
		|||
 | 
			
		||||
struct device_attribute {
 | 
			
		||||
	struct attribute	attr;
 | 
			
		||||
        ssize_t (*show)(struct device * dev, char * buf);
 | 
			
		||||
        ssize_t (*store)(struct device * dev, const char * buf);
 | 
			
		||||
	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			char *buf);
 | 
			
		||||
	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			 const char *buf, size_t count);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int device_create_file(struct device *, struct device_attribute *);
 | 
			
		||||
| 
						 | 
				
			
			@ -91,11 +96,7 @@ void device_remove_file(struct device *, struct device_attribute *);
 | 
			
		|||
It also defines this helper for defining device attributes: 
 | 
			
		||||
 | 
			
		||||
#define DEVICE_ATTR(_name, _mode, _show, _store) \
 | 
			
		||||
struct device_attribute dev_attr_##_name = {            \
 | 
			
		||||
        .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
 | 
			
		||||
        .show   = _show,                                \
 | 
			
		||||
        .store  = _store,                               \
 | 
			
		||||
};
 | 
			
		||||
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
 | 
			
		||||
 | 
			
		||||
For example, declaring
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,9 +108,9 @@ static struct device_attribute dev_attr_foo = {
 | 
			
		|||
       .attr	= {
 | 
			
		||||
		.name = "foo",
 | 
			
		||||
		.mode = S_IWUSR | S_IRUGO,
 | 
			
		||||
	},
 | 
			
		||||
		.show = show_foo,
 | 
			
		||||
		.store = store_foo,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -161,10 +162,12 @@ To read or write attributes, show() or store() methods must be
 | 
			
		|||
specified when declaring the attribute. The method types should be as
 | 
			
		||||
simple as those defined for device attributes:
 | 
			
		||||
 | 
			
		||||
        ssize_t (*show)(struct device * dev, char * buf);
 | 
			
		||||
        ssize_t (*store)(struct device * dev, const char * buf);
 | 
			
		||||
ssize_t (*show)(struct device * dev, struct device_attribute * attr,
 | 
			
		||||
                char * buf);
 | 
			
		||||
ssize_t (*store)(struct device * dev, struct device_attribute * attr,
 | 
			
		||||
                 const char * buf);
 | 
			
		||||
 | 
			
		||||
IOW, they should take only an object and a buffer as parameters. 
 | 
			
		||||
IOW, they should take only an object, an attribute, and a buffer as parameters.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
 | 
			
		||||
| 
						 | 
				
			
			@ -300,13 +303,15 @@ Structure:
 | 
			
		|||
 | 
			
		||||
struct device_attribute {
 | 
			
		||||
	struct attribute	attr;
 | 
			
		||||
        ssize_t (*show)(struct device * dev, char * buf);
 | 
			
		||||
        ssize_t (*store)(struct device * dev, const char * buf);
 | 
			
		||||
	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			char *buf);
 | 
			
		||||
	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 | 
			
		||||
			 const char *buf, size_t count);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Declaring:
 | 
			
		||||
 | 
			
		||||
DEVICE_ATTR(_name, _str, _mode, _show, _store);
 | 
			
		||||
DEVICE_ATTR(_name, _mode, _show, _store);
 | 
			
		||||
 | 
			
		||||
Creation/Removal:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -342,7 +347,8 @@ Structure:
 | 
			
		|||
struct driver_attribute {
 | 
			
		||||
        struct attribute        attr;
 | 
			
		||||
        ssize_t (*show)(struct device_driver *, char * buf);
 | 
			
		||||
        ssize_t (*store)(struct device_driver *, const char * buf);
 | 
			
		||||
        ssize_t (*store)(struct device_driver *, const char * buf,
 | 
			
		||||
                         size_t count);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Declaring:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ and is between 256 and 4096 characters. It is defined in the file
 | 
			
		|||
 | 
			
		||||
	acpi=		[HW,ACPI,X86-64,i386]
 | 
			
		||||
			Advanced Configuration and Power Interface
 | 
			
		||||
			Format: { force | off | ht | strict | noirq }
 | 
			
		||||
			Format: { force | off | ht | strict | noirq | rsdt }
 | 
			
		||||
			force -- enable ACPI if default was off
 | 
			
		||||
			off -- disable ACPI if default was on
 | 
			
		||||
			noirq -- do not use ACPI for IRQ routing
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3340,8 +3340,8 @@ P:	Jeremy Fitzhardinge
 | 
			
		|||
M:	jeremy@xensource.com
 | 
			
		||||
P:	Chris Wright
 | 
			
		||||
M:	chrisw@sous-sol.org
 | 
			
		||||
P:	Zachary Amsden
 | 
			
		||||
M:	zach@vmware.com
 | 
			
		||||
P:	Alok Kataria
 | 
			
		||||
M:	akataria@vmware.com
 | 
			
		||||
P:	Rusty Russell
 | 
			
		||||
M:	rusty@rustcorp.com.au
 | 
			
		||||
L:	virtualization@lists.osdl.org
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
VERSION = 2
 | 
			
		||||
PATCHLEVEL = 6
 | 
			
		||||
SUBLEVEL = 29
 | 
			
		||||
EXTRAVERSION = -rc5
 | 
			
		||||
EXTRAVERSION = -rc6
 | 
			
		||||
NAME = Erotic Pickled Herring
 | 
			
		||||
 | 
			
		||||
# *DOCUMENTATION*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								README
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -188,7 +188,7 @@ CONFIGURING the kernel:
 | 
			
		|||
			   values to random values.
 | 
			
		||||
 | 
			
		||||
   You can find more information on using the Linux kernel config tools
 | 
			
		||||
   in Documentation/kbuild/make-configs.txt.
 | 
			
		||||
   in Documentation/kbuild/kconfig.txt.
 | 
			
		||||
 | 
			
		||||
	NOTES on "make config":
 | 
			
		||||
	- having unnecessary drivers will make the kernel bigger, and can
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include <linux/serial_8250.h>
 | 
			
		||||
#include <linux/ata_platform.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/i2c.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/elf.h>
 | 
			
		||||
#include <asm/mach-types.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -201,8 +202,13 @@ static struct platform_device *devs[] __initdata = {
 | 
			
		|||
	&pata_device,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct i2c_board_info i2c_rtc = {
 | 
			
		||||
	I2C_BOARD_INFO("pcf8583", 0x50)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init rpc_init(void)
 | 
			
		||||
{
 | 
			
		||||
	i2c_register_board_info(0, &i2c_rtc, 1);
 | 
			
		||||
	return platform_add_devices(devs, ARRAY_SIZE(devs));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -224,7 +224,11 @@ config IA64_HP_SIM
 | 
			
		|||
 | 
			
		||||
config IA64_XEN_GUEST
 | 
			
		||||
	bool "Xen guest"
 | 
			
		||||
	select SWIOTLB
 | 
			
		||||
	depends on XEN
 | 
			
		||||
	help
 | 
			
		||||
	  Build a kernel that runs on Xen guest domain. At this moment only
 | 
			
		||||
	  16KB page size in supported.
 | 
			
		||||
 | 
			
		||||
endchoice
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -482,8 +486,7 @@ config HOLES_IN_ZONE
 | 
			
		|||
	default y if VIRTUAL_MEM_MAP
 | 
			
		||||
 | 
			
		||||
config HAVE_ARCH_EARLY_PFN_TO_NID
 | 
			
		||||
	def_bool y
 | 
			
		||||
	depends on NEED_MULTIPLE_NODES
 | 
			
		||||
	def_bool NUMA && SPARSEMEM
 | 
			
		||||
 | 
			
		||||
config HAVE_ARCH_NODEDATA_EXTENSION
 | 
			
		||||
	def_bool y
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1601
									
								
								arch/ia64/configs/xen_domu_defconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1601
									
								
								arch/ia64/configs/xen_domu_defconfig
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -39,7 +39,7 @@
 | 
			
		|||
/* BTE status register only supports 16 bits for length field */
 | 
			
		||||
#define BTE_LEN_BITS (16)
 | 
			
		||||
#define BTE_LEN_MASK ((1 << BTE_LEN_BITS) - 1)
 | 
			
		||||
#define BTE_MAX_XFER ((1 << BTE_LEN_BITS) * L1_CACHE_BYTES)
 | 
			
		||||
#define BTE_MAX_XFER (BTE_LEN_MASK << L1_CACHE_SHIFT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Define hardware */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -736,14 +736,15 @@ int __cpu_disable(void)
 | 
			
		|||
			return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cpu_clear(cpu, cpu_online_map);
 | 
			
		||||
 | 
			
		||||
	if (migrate_platform_irqs(cpu)) {
 | 
			
		||||
		cpu_set(cpu, cpu_online_map);
 | 
			
		||||
		return (-EBUSY);
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remove_siblinginfo(cpu);
 | 
			
		||||
	fixup_irqs();
 | 
			
		||||
	cpu_clear(cpu, cpu_online_map);
 | 
			
		||||
	local_flush_tlb_all();
 | 
			
		||||
	cpu_clear(cpu, cpu_callin_map);
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,9 +97,10 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
 | 
			
		|||
		return BTE_SUCCESS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	BUG_ON((len & L1_CACHE_MASK) ||
 | 
			
		||||
		 (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK));
 | 
			
		||||
	BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)));
 | 
			
		||||
	BUG_ON(len & L1_CACHE_MASK);
 | 
			
		||||
	BUG_ON(src & L1_CACHE_MASK);
 | 
			
		||||
	BUG_ON(dest & L1_CACHE_MASK);
 | 
			
		||||
	BUG_ON(len > BTE_MAX_XFER);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Start with interface corresponding to cpu number
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,8 +8,7 @@ config XEN
 | 
			
		|||
	depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
 | 
			
		||||
	select XEN_XENCOMM
 | 
			
		||||
	select NO_IDLE_HZ
 | 
			
		||||
 | 
			
		||||
	# those are required to save/restore.
 | 
			
		||||
	# followings are required to save/restore.
 | 
			
		||||
	select ARCH_SUSPEND_POSSIBLE
 | 
			
		||||
	select SUSPEND
 | 
			
		||||
	select PM_SLEEP
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ xen_post_smp_prepare_boot_cpu(void)
 | 
			
		|||
	xen_setup_vcpu_info_placement();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pv_init_ops xen_init_ops __initdata = {
 | 
			
		||||
static const struct pv_init_ops xen_init_ops __initconst = {
 | 
			
		||||
	.banner = xen_banner,
 | 
			
		||||
 | 
			
		||||
	.reserve_memory = xen_reserve_memory,
 | 
			
		||||
| 
						 | 
				
			
			@ -337,7 +337,7 @@ xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
 | 
			
		|||
	HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pv_iosapic_ops xen_iosapic_ops __initdata = {
 | 
			
		||||
static const struct pv_iosapic_ops xen_iosapic_ops __initconst = {
 | 
			
		||||
	.pcat_compat_init = xen_pcat_compat_init,
 | 
			
		||||
	.__get_irq_chip = xen_iosapic_get_irq_chip,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -187,8 +187,8 @@ __asm__ (__ALIGN_STR "\n"						   \
 | 
			
		|||
"	jbra	ret_from_interrupt\n"					   \
 | 
			
		||||
	 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),	   \
 | 
			
		||||
	     "n" (PT_OFF_SR), "n" (n),					   \
 | 
			
		||||
	     "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a)	   \
 | 
			
		||||
		        : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)),	   \
 | 
			
		||||
	     "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
 | 
			
		||||
		        : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
 | 
			
		||||
	     "m" (preempt_count()), "di" (HARDIRQ_OFFSET)		   \
 | 
			
		||||
);									   \
 | 
			
		||||
	for (;;);			/* fake noreturn */		   \
 | 
			
		||||
| 
						 | 
				
			
			@ -366,14 +366,14 @@ void __init atari_init_IRQ(void)
 | 
			
		|||
	/* Initialize the MFP(s) */
 | 
			
		||||
 | 
			
		||||
#ifdef ATARI_USE_SOFTWARE_EOI
 | 
			
		||||
	mfp.vec_adr  = 0x48;	/* Software EOI-Mode */
 | 
			
		||||
	st_mfp.vec_adr  = 0x48;	/* Software EOI-Mode */
 | 
			
		||||
#else
 | 
			
		||||
	mfp.vec_adr  = 0x40;	/* Automatic EOI-Mode */
 | 
			
		||||
	st_mfp.vec_adr  = 0x40;	/* Automatic EOI-Mode */
 | 
			
		||||
#endif
 | 
			
		||||
	mfp.int_en_a = 0x00;	/* turn off MFP-Ints */
 | 
			
		||||
	mfp.int_en_b = 0x00;
 | 
			
		||||
	mfp.int_mk_a = 0xff;	/* no Masking */
 | 
			
		||||
	mfp.int_mk_b = 0xff;
 | 
			
		||||
	st_mfp.int_en_a = 0x00;	/* turn off MFP-Ints */
 | 
			
		||||
	st_mfp.int_en_b = 0x00;
 | 
			
		||||
	st_mfp.int_mk_a = 0xff;	/* no Masking */
 | 
			
		||||
	st_mfp.int_mk_b = 0xff;
 | 
			
		||||
 | 
			
		||||
	if (ATARIHW_PRESENT(TT_MFP)) {
 | 
			
		||||
#ifdef ATARI_USE_SOFTWARE_EOI
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -609,10 +609,10 @@ int atari_keyb_init(void)
 | 
			
		|||
				 ACIA_RHTID : 0);
 | 
			
		||||
 | 
			
		||||
	/* make sure the interrupt line is up */
 | 
			
		||||
	} while ((mfp.par_dt_reg & 0x10) == 0);
 | 
			
		||||
	} while ((st_mfp.par_dt_reg & 0x10) == 0);
 | 
			
		||||
 | 
			
		||||
	/* enable ACIA Interrupts */
 | 
			
		||||
	mfp.active_edge &= ~0x10;
 | 
			
		||||
	st_mfp.active_edge &= ~0x10;
 | 
			
		||||
	atari_turnon_irq(IRQ_MFP_ACIA);
 | 
			
		||||
 | 
			
		||||
	ikbd_self_test = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,7 +258,7 @@ void __init config_atari(void)
 | 
			
		|||
			printk("STND_SHIFTER ");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (hwreg_present(&mfp.par_dt_reg)) {
 | 
			
		||||
	if (hwreg_present(&st_mfp.par_dt_reg)) {
 | 
			
		||||
		ATARIHW_SET(ST_MFP);
 | 
			
		||||
		printk("ST_MFP ");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,9 +34,9 @@ static struct console atari_console_driver = {
 | 
			
		|||
 | 
			
		||||
static inline void ata_mfp_out(char c)
 | 
			
		||||
{
 | 
			
		||||
	while (!(mfp.trn_stat & 0x80))	/* wait for tx buf empty */
 | 
			
		||||
	while (!(st_mfp.trn_stat & 0x80))	/* wait for tx buf empty */
 | 
			
		||||
		barrier();
 | 
			
		||||
	mfp.usart_dta = c;
 | 
			
		||||
	st_mfp.usart_dta = c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atari_mfp_console_write(struct console *co, const char *str,
 | 
			
		||||
| 
						 | 
				
			
			@ -91,7 +91,7 @@ static int ata_par_out(char c)
 | 
			
		|||
	/* This a some-seconds timeout in case no printer is connected */
 | 
			
		||||
	unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
 | 
			
		||||
 | 
			
		||||
	while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
 | 
			
		||||
	while ((st_mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
 | 
			
		||||
		;
 | 
			
		||||
	if (!i)
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -131,9 +131,9 @@ static void atari_par_console_write(struct console *co, const char *str,
 | 
			
		|||
#if 0
 | 
			
		||||
int atari_mfp_console_wait_key(struct console *co)
 | 
			
		||||
{
 | 
			
		||||
	while (!(mfp.rcv_stat & 0x80))	/* wait for rx buf filled */
 | 
			
		||||
	while (!(st_mfp.rcv_stat & 0x80))	/* wait for rx buf filled */
 | 
			
		||||
		barrier();
 | 
			
		||||
	return mfp.usart_dta;
 | 
			
		||||
	return st_mfp.usart_dta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int atari_scc_console_wait_key(struct console *co)
 | 
			
		||||
| 
						 | 
				
			
			@ -175,12 +175,12 @@ static void __init atari_init_mfp_port(int cflag)
 | 
			
		|||
		baud = B9600;		/* use default 9600bps for non-implemented rates */
 | 
			
		||||
	baud -= B1200;			/* baud_table[] starts at 1200bps */
 | 
			
		||||
 | 
			
		||||
	mfp.trn_stat &= ~0x01;		/* disable TX */
 | 
			
		||||
	mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
 | 
			
		||||
	mfp.tim_ct_cd &= 0x70;		/* stop timer D */
 | 
			
		||||
	mfp.tim_dt_d = baud_table[baud];
 | 
			
		||||
	mfp.tim_ct_cd |= 0x01;		/* start timer D, 1:4 */
 | 
			
		||||
	mfp.trn_stat |= 0x01;		/* enable TX */
 | 
			
		||||
	st_mfp.trn_stat &= ~0x01;	/* disable TX */
 | 
			
		||||
	st_mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
 | 
			
		||||
	st_mfp.tim_ct_cd &= 0x70;	/* stop timer D */
 | 
			
		||||
	st_mfp.tim_dt_d = baud_table[baud];
 | 
			
		||||
	st_mfp.tim_ct_cd |= 0x01;	/* start timer D, 1:4 */
 | 
			
		||||
	st_mfp.trn_stat |= 0x01;	/* enable TX */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SCC_WRITE(reg, val)				\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,9 @@ void __init
 | 
			
		|||
atari_sched_init(irq_handler_t timer_routine)
 | 
			
		||||
{
 | 
			
		||||
    /* set Timer C data Register */
 | 
			
		||||
    mfp.tim_dt_c = INT_TICKS;
 | 
			
		||||
    st_mfp.tim_dt_c = INT_TICKS;
 | 
			
		||||
    /* start timer C, div = 1:100 */
 | 
			
		||||
    mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
 | 
			
		||||
    st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
 | 
			
		||||
    /* install interrupt service routine for MFP Timer C */
 | 
			
		||||
    if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
 | 
			
		||||
		    "timer", timer_routine))
 | 
			
		||||
| 
						 | 
				
			
			@ -46,11 +46,11 @@ unsigned long atari_gettimeoffset (void)
 | 
			
		|||
  unsigned long ticks, offset = 0;
 | 
			
		||||
 | 
			
		||||
  /* read MFP timer C current value */
 | 
			
		||||
  ticks = mfp.tim_dt_c;
 | 
			
		||||
  ticks = st_mfp.tim_dt_c;
 | 
			
		||||
  /* The probability of underflow is less than 2% */
 | 
			
		||||
  if (ticks > INT_TICKS - INT_TICKS / 50)
 | 
			
		||||
    /* Check for pending timer interrupt */
 | 
			
		||||
    if (mfp.int_pn_b & (1 << 5))
 | 
			
		||||
    if (st_mfp.int_pn_b & (1 << 5))
 | 
			
		||||
      offset = TICK_SIZE;
 | 
			
		||||
 | 
			
		||||
  ticks = INT_TICKS - ticks;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ extern struct atari_hw_present atari_hw_present;
 | 
			
		|||
 * of nops on various machines. Somebody claimed that the tstb takes 600 ns.
 | 
			
		||||
 */
 | 
			
		||||
#define	MFPDELAY() \
 | 
			
		||||
	__asm__ __volatile__ ( "tstb %0" : : "m" (mfp.par_dt_reg) : "cc" );
 | 
			
		||||
	__asm__ __volatile__ ( "tstb %0" : : "m" (st_mfp.par_dt_reg) : "cc" );
 | 
			
		||||
 | 
			
		||||
/* Do cache push/invalidate for DMA read/write. This function obeys the
 | 
			
		||||
 * snooping on some machines (Medusa) and processors: The Medusa itself can
 | 
			
		||||
| 
						 | 
				
			
			@ -565,7 +565,7 @@ struct MFP
 | 
			
		|||
  u_char char_dummy23;
 | 
			
		||||
  u_char usart_dta;
 | 
			
		||||
 };
 | 
			
		||||
# define mfp ((*(volatile struct MFP*)MFP_BAS))
 | 
			
		||||
# define st_mfp ((*(volatile struct MFP*)MFP_BAS))
 | 
			
		||||
 | 
			
		||||
/* TT's second MFP */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ static inline int get_mfp_bit( unsigned irq, int type )
 | 
			
		|||
{	unsigned char	mask, *reg;
 | 
			
		||||
 | 
			
		||||
	mask = 1 << (irq & 7);
 | 
			
		||||
	reg = (unsigned char *)&mfp.int_en_a + type*4 +
 | 
			
		||||
	reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
 | 
			
		||||
		  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
 | 
			
		||||
	return( *reg & mask );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ static inline void set_mfp_bit( unsigned irq, int type )
 | 
			
		|||
{	unsigned char	mask, *reg;
 | 
			
		||||
 | 
			
		||||
	mask = 1 << (irq & 7);
 | 
			
		||||
	reg = (unsigned char *)&mfp.int_en_a + type*4 +
 | 
			
		||||
	reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
 | 
			
		||||
		  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
 | 
			
		||||
	__asm__ __volatile__ ( "orb %0,%1"
 | 
			
		||||
			      : : "di" (mask), "m" (*reg) : "memory" );
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +134,7 @@ static inline void clear_mfp_bit( unsigned irq, int type )
 | 
			
		|||
{	unsigned char	mask, *reg;
 | 
			
		||||
 | 
			
		||||
	mask = ~(1 << (irq & 7));
 | 
			
		||||
	reg = (unsigned char *)&mfp.int_en_a + type*4 +
 | 
			
		||||
	reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
 | 
			
		||||
		  ((irq & 8) >> 2) + (((irq-8) & 16) << 3);
 | 
			
		||||
	if (type == MFP_PENDING || type == MFP_SERVICE)
 | 
			
		||||
		__asm__ __volatile__ ( "moveb %0,%1"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ mainmenu "Linux Kernel Configuration"
 | 
			
		|||
 | 
			
		||||
config MN10300
 | 
			
		||||
	def_bool y
 | 
			
		||||
	select HAVE_OPROFILE
 | 
			
		||||
 | 
			
		||||
config AM33
 | 
			
		||||
	def_bool y
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -173,7 +173,7 @@ static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
 | 
			
		|||
		BRIDGEREGB(where) = value;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (bus->number == 0 &&
 | 
			
		||||
		    (devfn == PCI_DEVFN(2, 0) && devfn == PCI_DEVFN(3, 0))
 | 
			
		||||
		    (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
 | 
			
		||||
		    )
 | 
			
		||||
			__pcidebug("<= %02x", bus, devfn, where, value);
 | 
			
		||||
		CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
 | 
			
		|||
{
 | 
			
		||||
	struct vde_open_args *args;
 | 
			
		||||
 | 
			
		||||
	vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
 | 
			
		||||
	vpri->args = uml_kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
 | 
			
		||||
	if (vpri->args == NULL) {
 | 
			
		||||
		printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
 | 
			
		||||
		       "allocation failed");
 | 
			
		||||
| 
						 | 
				
			
			@ -91,8 +91,8 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
 | 
			
		|||
	args->group = init->group;
 | 
			
		||||
	args->mode = init->mode ? init->mode : 0700;
 | 
			
		||||
 | 
			
		||||
	args->port ?  printk(UM_KERN_INFO "port %d", args->port) :
 | 
			
		||||
		printk(UM_KERN_INFO "undefined port");
 | 
			
		||||
	args->port ?  printk("port %d", args->port) :
 | 
			
		||||
		printk("undefined port");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int vde_user_read(void *conn, void *buf, int len)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,8 +80,6 @@
 | 
			
		|||
 | 
			
		||||
#define PTRACE_SINGLEBLOCK	33	/* resume execution until next branch */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_X86_PTRACE_BTS
 | 
			
		||||
 | 
			
		||||
#ifndef __ASSEMBLY__
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,6 +138,5 @@ struct ptrace_bts_config {
 | 
			
		|||
   BTS records are read from oldest to newest.
 | 
			
		||||
   Returns number of BTS records drained.
 | 
			
		||||
*/
 | 
			
		||||
#endif /* CONFIG_X86_PTRACE_BTS */
 | 
			
		||||
 | 
			
		||||
#endif /* _ASM_X86_PTRACE_ABI_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,6 @@
 | 
			
		|||
	 * Hooray, we are in Long 64-bit mode (but still running in low memory)
 | 
			
		||||
	 */
 | 
			
		||||
ENTRY(wakeup_long64)
 | 
			
		||||
wakeup_long64:
 | 
			
		||||
	movq	saved_magic, %rax
 | 
			
		||||
	movq	$0x123456789abcdef0, %rdx
 | 
			
		||||
	cmpq	%rdx, %rax
 | 
			
		||||
| 
						 | 
				
			
			@ -34,16 +33,12 @@ wakeup_long64:
 | 
			
		|||
 | 
			
		||||
	movq	saved_rip, %rax
 | 
			
		||||
	jmp	*%rax
 | 
			
		||||
ENDPROC(wakeup_long64)
 | 
			
		||||
 | 
			
		||||
bogus_64_magic:
 | 
			
		||||
	jmp	bogus_64_magic
 | 
			
		||||
 | 
			
		||||
	.align 2
 | 
			
		||||
	.p2align 4,,15
 | 
			
		||||
.globl do_suspend_lowlevel
 | 
			
		||||
	.type	do_suspend_lowlevel,@function
 | 
			
		||||
do_suspend_lowlevel:
 | 
			
		||||
.LFB5:
 | 
			
		||||
ENTRY(do_suspend_lowlevel)
 | 
			
		||||
	subq	$8, %rsp
 | 
			
		||||
	xorl	%eax, %eax
 | 
			
		||||
	call	save_processor_state
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +62,7 @@ do_suspend_lowlevel:
 | 
			
		|||
	pushfq
 | 
			
		||||
	popq	pt_regs_flags(%rax)
 | 
			
		||||
 | 
			
		||||
	movq	$.L97, saved_rip(%rip)
 | 
			
		||||
	movq	$resume_point, saved_rip(%rip)
 | 
			
		||||
 | 
			
		||||
	movq	%rsp, saved_rsp
 | 
			
		||||
	movq	%rbp, saved_rbp
 | 
			
		||||
| 
						 | 
				
			
			@ -78,14 +73,12 @@ do_suspend_lowlevel:
 | 
			
		|||
	addq	$8, %rsp
 | 
			
		||||
	movl	$3, %edi
 | 
			
		||||
	xorl	%eax, %eax
 | 
			
		||||
	jmp	acpi_enter_sleep_state
 | 
			
		||||
.L97:
 | 
			
		||||
	.p2align 4,,7
 | 
			
		||||
.L99:
 | 
			
		||||
	.align 4
 | 
			
		||||
	movl	$24, %eax
 | 
			
		||||
	movw	%ax, %ds
 | 
			
		||||
	call	acpi_enter_sleep_state
 | 
			
		||||
	/* in case something went wrong, restore the machine status and go on */
 | 
			
		||||
	jmp	resume_point
 | 
			
		||||
 | 
			
		||||
	.align 4
 | 
			
		||||
resume_point:
 | 
			
		||||
	/* We don't restore %rax, it must be 0 anyway */
 | 
			
		||||
	movq	$saved_context, %rax
 | 
			
		||||
	movq	saved_context_cr4(%rax), %rbx
 | 
			
		||||
| 
						 | 
				
			
			@ -117,12 +110,9 @@ do_suspend_lowlevel:
 | 
			
		|||
	xorl	%eax, %eax
 | 
			
		||||
	addq	$8, %rsp
 | 
			
		||||
	jmp	restore_processor_state
 | 
			
		||||
.LFE5:
 | 
			
		||||
.Lfe5:
 | 
			
		||||
	.size	do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
 | 
			
		||||
ENDPROC(do_suspend_lowlevel)
 | 
			
		||||
 | 
			
		||||
.data
 | 
			
		||||
ALIGN
 | 
			
		||||
ENTRY(saved_rbp)	.quad	0
 | 
			
		||||
ENTRY(saved_rsi)	.quad	0
 | 
			
		||||
ENTRY(saved_rdi)	.quad	0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1192,6 +1192,7 @@ static int suspend(int vetoable)
 | 
			
		|||
	device_suspend(PMSG_SUSPEND);
 | 
			
		||||
	local_irq_disable();
 | 
			
		||||
	device_power_down(PMSG_SUSPEND);
 | 
			
		||||
	sysdev_suspend(PMSG_SUSPEND);
 | 
			
		||||
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1208,6 +1209,7 @@ static int suspend(int vetoable)
 | 
			
		|||
	if (err != APM_SUCCESS)
 | 
			
		||||
		apm_error("suspend", err);
 | 
			
		||||
	err = (err == APM_SUCCESS) ? 0 : -EIO;
 | 
			
		||||
	sysdev_resume();
 | 
			
		||||
	device_power_up(PMSG_RESUME);
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
	device_resume(PMSG_RESUME);
 | 
			
		||||
| 
						 | 
				
			
			@ -1228,6 +1230,7 @@ static void standby(void)
 | 
			
		|||
 | 
			
		||||
	local_irq_disable();
 | 
			
		||||
	device_power_down(PMSG_SUSPEND);
 | 
			
		||||
	sysdev_suspend(PMSG_SUSPEND);
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
 | 
			
		||||
	err = set_system_power_state(APM_STATE_STANDBY);
 | 
			
		||||
| 
						 | 
				
			
			@ -1235,6 +1238,7 @@ static void standby(void)
 | 
			
		|||
		apm_error("standby", err);
 | 
			
		||||
 | 
			
		||||
	local_irq_disable();
 | 
			
		||||
	sysdev_resume();
 | 
			
		||||
	device_power_up(PMSG_RESUME);
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -490,7 +490,7 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
 | 
			
		||||
static void mce_cpu_features(struct cpuinfo_x86 *c)
 | 
			
		||||
{
 | 
			
		||||
	switch (c->x86_vendor) {
 | 
			
		||||
	case X86_VENDOR_INTEL:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,7 +121,7 @@ static long threshold_restart_bank(void *_tr)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/* cpu init entry point, called from mce.c with preempt off */
 | 
			
		||||
void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
 | 
			
		||||
void mce_amd_feature_init(struct cpuinfo_x86 *c)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int bank, block;
 | 
			
		||||
	unsigned int cpu = smp_processor_id();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ asmlinkage void smp_thermal_interrupt(void)
 | 
			
		|||
	irq_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
 | 
			
		||||
static void intel_init_thermal(struct cpuinfo_x86 *c)
 | 
			
		||||
{
 | 
			
		||||
	u32 l, h;
 | 
			
		||||
	int tm2 = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
 | 
			
		|||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
 | 
			
		||||
void mce_intel_feature_init(struct cpuinfo_x86 *c)
 | 
			
		||||
{
 | 
			
		||||
	intel_init_thermal(c);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ unsigned long __init calibrate_cpu(void)
 | 
			
		|||
 | 
			
		||||
static struct irqaction irq0 = {
 | 
			
		||||
	.handler	= timer_interrupt,
 | 
			
		||||
	.flags		= IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
 | 
			
		||||
	.flags		= IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING | IRQF_TIMER,
 | 
			
		||||
	.mask		= CPU_MASK_NONE,
 | 
			
		||||
	.name		= "timer"
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
 | 
			
		|||
static struct irqaction vmi_clock_action  = {
 | 
			
		||||
	.name 		= "vmi-timer",
 | 
			
		||||
	.handler 	= vmi_timer_interrupt,
 | 
			
		||||
	.flags 		= IRQF_DISABLED | IRQF_NOBALANCING,
 | 
			
		||||
	.flags 		= IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
 | 
			
		||||
	.mask 		= CPU_MASK_ALL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,7 +96,7 @@ void __init trap_init_hook(void)
 | 
			
		|||
 | 
			
		||||
static struct irqaction irq0  = {
 | 
			
		||||
	.handler = timer_interrupt,
 | 
			
		||||
	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
 | 
			
		||||
	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
 | 
			
		||||
	.mask = CPU_MASK_NONE,
 | 
			
		||||
	.name = "timer"
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ void __init trap_init_hook(void)
 | 
			
		|||
 | 
			
		||||
static struct irqaction irq0 = {
 | 
			
		||||
	.handler = timer_interrupt,
 | 
			
		||||
	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
 | 
			
		||||
	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
 | 
			
		||||
	.mask = CPU_MASK_NONE,
 | 
			
		||||
	.name = "timer"
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -214,7 +214,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
 | 
			
		|||
	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 | 
			
		||||
					     "yes" : "no");
 | 
			
		||||
	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 | 
			
		||||
	seq_printf(m, "digestsize   : %u\n", alg->cra_hash.digestsize);
 | 
			
		||||
	seq_printf(m, "digestsize   : %u\n", alg->cra_ahash.digestsize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct crypto_type crypto_ahash_type = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -254,13 +254,6 @@ config ACPI_PCI_SLOT
 | 
			
		|||
	  help you correlate PCI bus addresses with the physical geography
 | 
			
		||||
	  of your slots. If you are unsure, say N.
 | 
			
		||||
 | 
			
		||||
config ACPI_SYSTEM
 | 
			
		||||
	bool
 | 
			
		||||
	default y
 | 
			
		||||
	help
 | 
			
		||||
	  This driver will enable your system to shut down using ACPI, and
 | 
			
		||||
	  dump your ACPI DSDT table using /proc/acpi/dsdt.
 | 
			
		||||
 | 
			
		||||
config X86_PM_TIMER
 | 
			
		||||
	bool "Power Management Timer Support" if EMBEDDED
 | 
			
		||||
	depends on X86
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,7 +52,7 @@ obj-$(CONFIG_ACPI_PROCESSOR)	+= processor.o
 | 
			
		|||
obj-$(CONFIG_ACPI_CONTAINER)	+= container.o
 | 
			
		||||
obj-$(CONFIG_ACPI_THERMAL)	+= thermal.o
 | 
			
		||||
obj-y				+= power.o
 | 
			
		||||
obj-$(CONFIG_ACPI_SYSTEM)	+= system.o event.o
 | 
			
		||||
obj-y				+= system.o event.o
 | 
			
		||||
obj-$(CONFIG_ACPI_DEBUG)	+= debug.o
 | 
			
		||||
obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 | 
			
		||||
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)	+= acpi_memhotplug.o
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,6 +138,29 @@ static int acpi_battery_technology(struct acpi_battery *battery)
 | 
			
		|||
 | 
			
		||||
static int acpi_battery_get_state(struct acpi_battery *battery);
 | 
			
		||||
 | 
			
		||||
static int acpi_battery_is_charged(struct acpi_battery *battery)
 | 
			
		||||
{
 | 
			
		||||
	/* either charging or discharging */
 | 
			
		||||
	if (battery->state != 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* battery not reporting charge */
 | 
			
		||||
	if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
 | 
			
		||||
	    battery->capacity_now == 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* good batteries update full_charge as the batteries degrade */
 | 
			
		||||
	if (battery->full_charge_capacity == battery->capacity_now)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* fallback to using design values for broken batteries */
 | 
			
		||||
	if (battery->design_capacity == battery->capacity_now)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/* we don't do any sort of metric based on percentages */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int acpi_battery_get_property(struct power_supply *psy,
 | 
			
		||||
				     enum power_supply_property psp,
 | 
			
		||||
				     union power_supply_propval *val)
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +178,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
 | 
			
		|||
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 | 
			
		||||
		else if (battery->state & 0x02)
 | 
			
		||||
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
 | 
			
		||||
		else if (battery->state == 0)
 | 
			
		||||
		else if (acpi_battery_is_charged(battery))
 | 
			
		||||
			val->intval = POWER_SUPPLY_STATUS_FULL;
 | 
			
		||||
		else
 | 
			
		||||
			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,6 +120,8 @@ static struct acpi_ec {
 | 
			
		|||
	spinlock_t curr_lock;
 | 
			
		||||
} *boot_ec, *first_ec;
 | 
			
		||||
 | 
			
		||||
static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
 | 
			
		||||
 | 
			
		||||
/* --------------------------------------------------------------------------
 | 
			
		||||
                             Transaction Management
 | 
			
		||||
   -------------------------------------------------------------------------- */
 | 
			
		||||
| 
						 | 
				
			
			@ -259,6 +261,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
 | 
			
		|||
		clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
 | 
			
		||||
		acpi_disable_gpe(NULL, ec->gpe);
 | 
			
		||||
	}
 | 
			
		||||
	if (EC_FLAGS_MSI)
 | 
			
		||||
		udelay(ACPI_EC_DELAY);
 | 
			
		||||
	/* start transaction */
 | 
			
		||||
	spin_lock_irqsave(&ec->curr_lock, tmp);
 | 
			
		||||
	/* following two actions should be kept atomic */
 | 
			
		||||
| 
						 | 
				
			
			@ -967,6 +971,11 @@ int __init acpi_ec_ecdt_probe(void)
 | 
			
		|||
	/*
 | 
			
		||||
	 * Generate a boot ec context
 | 
			
		||||
	 */
 | 
			
		||||
	if (dmi_name_in_vendors("Micro-Star") ||
 | 
			
		||||
	    dmi_name_in_vendors("Notebook")) {
 | 
			
		||||
		pr_info(PREFIX "Enabling special treatment for EC from MSI.\n");
 | 
			
		||||
		EC_FLAGS_MSI = 1;
 | 
			
		||||
	}
 | 
			
		||||
	status = acpi_get_table(ACPI_SIG_ECDT, 1,
 | 
			
		||||
				(struct acpi_table_header **)&ecdt_ptr);
 | 
			
		||||
	if (ACPI_SUCCESS(status)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -901,7 +901,7 @@ static int __devinit eeprom_read(struct lanai_dev *lanai)
 | 
			
		|||
		clock_l(); udelay(5);
 | 
			
		||||
		for (i = 128; i != 0; i >>= 1) {   /* write command out */
 | 
			
		||||
			tmp = (lanai->conf1 & ~CONFIG1_PROMDATA) |
 | 
			
		||||
			    (data & i) ? CONFIG1_PROMDATA : 0;
 | 
			
		||||
			    ((data & i) ? CONFIG1_PROMDATA : 0);
 | 
			
		||||
			if (lanai->conf1 != tmp) {
 | 
			
		||||
				set_config1(tmp);
 | 
			
		||||
				udelay(5);	/* Let new data settle */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,8 +88,6 @@ extern void driver_detach(struct device_driver *drv);
 | 
			
		|||
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
 | 
			
		||||
 | 
			
		||||
extern void sysdev_shutdown(void);
 | 
			
		||||
extern int sysdev_suspend(pm_message_t state);
 | 
			
		||||
extern int sysdev_resume(void);
 | 
			
		||||
 | 
			
		||||
extern char *make_class_name(const char *name, struct kobject *kobj);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,11 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/kthread.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/async.h>
 | 
			
		||||
 | 
			
		||||
#include "base.h"
 | 
			
		||||
#include "power/power.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -167,6 +169,21 @@ int driver_probe_done(void)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * wait_for_device_probe
 | 
			
		||||
 * Wait for device probing to be completed.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: this function polls at 100 msec intervals.
 | 
			
		||||
 */
 | 
			
		||||
int wait_for_device_probe(void)
 | 
			
		||||
{
 | 
			
		||||
	/* wait for the known devices to complete their probing */
 | 
			
		||||
	while (driver_probe_done() != 0)
 | 
			
		||||
		msleep(100);
 | 
			
		||||
	async_synchronize_full();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * driver_probe_device - attempt to bind device & driver together
 | 
			
		||||
 * @drv: driver to bind a device to
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -333,7 +333,6 @@ static void dpm_power_up(pm_message_t state)
 | 
			
		|||
 */
 | 
			
		||||
void device_power_up(pm_message_t state)
 | 
			
		||||
{
 | 
			
		||||
	sysdev_resume();
 | 
			
		||||
	dpm_power_up(state);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(device_power_up);
 | 
			
		||||
| 
						 | 
				
			
			@ -577,8 +576,6 @@ int device_power_down(pm_message_t state)
 | 
			
		|||
		}
 | 
			
		||||
		dev->power.status = DPM_OFF_IRQ;
 | 
			
		||||
	}
 | 
			
		||||
	if (!error)
 | 
			
		||||
		error = sysdev_suspend(state);
 | 
			
		||||
	if (error)
 | 
			
		||||
		dpm_power_up(resume_event(state));
 | 
			
		||||
	return error;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -303,7 +303,6 @@ void sysdev_unregister(struct sys_device * sysdev)
 | 
			
		|||
 *	is guaranteed by virtue of the fact that child devices are registered
 | 
			
		||||
 *	after their parents.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void sysdev_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sysdev_class * cls;
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +362,6 @@ static void __sysdev_resume(struct sys_device *dev)
 | 
			
		|||
 *	This is only called by the device PM core, so we let them handle
 | 
			
		||||
 *	all synchronization.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int sysdev_suspend(pm_message_t state)
 | 
			
		||||
{
 | 
			
		||||
	struct sysdev_class * cls;
 | 
			
		||||
| 
						 | 
				
			
			@ -432,7 +430,7 @@ int sysdev_suspend(pm_message_t state)
 | 
			
		|||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL_GPL(sysdev_suspend);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	sysdev_resume - Bring system devices back to life.
 | 
			
		||||
| 
						 | 
				
			
			@ -442,7 +440,6 @@ int sysdev_suspend(pm_message_t state)
 | 
			
		|||
 *
 | 
			
		||||
 *	Note: Interrupts are disabled when called.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int sysdev_resume(void)
 | 
			
		||||
{
 | 
			
		||||
	struct sysdev_class * cls;
 | 
			
		||||
| 
						 | 
				
			
			@ -463,7 +460,7 @@ int sysdev_resume(void)
 | 
			
		|||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL_GPL(sysdev_resume);
 | 
			
		||||
 | 
			
		||||
int __init system_bus_init(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1730,7 +1730,7 @@ static int __init fd_test_drive_present( int drive )
 | 
			
		|||
 | 
			
		||||
	timeout = jiffies + 2*HZ+HZ/2;
 | 
			
		||||
	while (time_before(jiffies, timeout))
 | 
			
		||||
		if (!(mfp.par_dt_reg & 0x20))
 | 
			
		||||
		if (!(st_mfp.par_dt_reg & 0x20))
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
	status = FDC_READ( FDCREG_STATUS );
 | 
			
		||||
| 
						 | 
				
			
			@ -1747,7 +1747,7 @@ static int __init fd_test_drive_present( int drive )
 | 
			
		|||
		/* dummy seek command to make WP bit accessible */
 | 
			
		||||
		FDC_WRITE( FDCREG_DATA, 0 );
 | 
			
		||||
		FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK );
 | 
			
		||||
		while( mfp.par_dt_reg & 0x20 )
 | 
			
		||||
		while( st_mfp.par_dt_reg & 0x20 )
 | 
			
		||||
			;
 | 
			
		||||
		status = FDC_READ( FDCREG_STATUS );
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -387,7 +387,7 @@ struct scc_port {
 | 
			
		|||
/* The SCC needs 3.5 PCLK cycles recovery time between to register
 | 
			
		||||
 * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
 | 
			
		||||
 * 125 ns = 437.5 ns. This is too short for udelay().
 | 
			
		||||
 * 10/16/95: A tstb mfp.par_dt_reg takes 600ns (sure?) and thus should be
 | 
			
		||||
 * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
 | 
			
		||||
 * quite right
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1746,9 +1746,10 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
 | 
			
		|||
		sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
 | 
			
		||||
		break;
 | 
			
		||||
	case SXIO_DO_RAMTEST:
 | 
			
		||||
		if (sx_initialized)	/* Already initialized: better not ramtest the board.  */
 | 
			
		||||
		if (sx_initialized) {	/* Already initialized: better not ramtest the board.  */
 | 
			
		||||
			rc = -EPERM;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (IS_SX_BOARD(board)) {
 | 
			
		||||
			rc = do_memtest(board, 0, 0x7000);
 | 
			
		||||
			if (!rc)
 | 
			
		||||
| 
						 | 
				
			
			@ -1788,7 +1789,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
 | 
			
		|||
						nbytes - i : SX_CHUNK_SIZE)) {
 | 
			
		||||
					kfree(tmp);
 | 
			
		||||
					rc = -EFAULT;
 | 
			
		||||
					break;
 | 
			
		||||
					goto out;
 | 
			
		||||
				}
 | 
			
		||||
				memcpy_toio(board->base2 + offset + i, tmp,
 | 
			
		||||
						(i + SX_CHUNK_SIZE > nbytes) ?
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1741,9 +1741,8 @@ int drm_mode_getfb(struct drm_device *dev,
 | 
			
		|||
 * RETURNS:
 | 
			
		||||
 * Zero on success, errno on failure.
 | 
			
		||||
 */
 | 
			
		||||
void drm_fb_release(struct file *filp)
 | 
			
		||||
void drm_fb_release(struct drm_file *priv)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_file *priv = filp->private_data;
 | 
			
		||||
	struct drm_device *dev = priv->minor->dev;
 | 
			
		||||
	struct drm_framebuffer *fb, *tfb;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -512,7 +512,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 | 
			
		|||
	if (drm_mode_equal(&saved_mode, &crtc->mode)) {
 | 
			
		||||
		if (saved_x != crtc->x || saved_y != crtc->y ||
 | 
			
		||||
		    depth_changed || bpp_changed) {
 | 
			
		||||
			crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
 | 
			
		||||
			ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
 | 
			
		||||
							 old_fb);
 | 
			
		||||
			goto done;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 | 
			
		|||
	/* Set up the DPLL and any encoders state that needs to adjust or depend
 | 
			
		||||
	 * on the DPLL.
 | 
			
		||||
	 */
 | 
			
		||||
	crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 | 
			
		||||
	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
	    goto done;
 | 
			
		||||
 | 
			
		||||
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 | 
			
		|||
			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 | 
			
		||||
						      set->x, set->y,
 | 
			
		||||
						      old_fb)) {
 | 
			
		||||
				DRM_ERROR("failed to set mode on crtc %p\n",
 | 
			
		||||
					  set->crtc);
 | 
			
		||||
				ret = -EINVAL;
 | 
			
		||||
				goto fail_set_mode;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 | 
			
		|||
		old_fb = set->crtc->fb;
 | 
			
		||||
		if (set->crtc->fb != set->fb)
 | 
			
		||||
			set->crtc->fb = set->fb;
 | 
			
		||||
		crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb);
 | 
			
		||||
		ret = crtc_funcs->mode_set_base(set->crtc,
 | 
			
		||||
						set->x, set->y, old_fb);
 | 
			
		||||
		if (ret != 0)
 | 
			
		||||
		    goto fail_set_mode;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kfree(save_encoders);
 | 
			
		||||
| 
						 | 
				
			
			@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 | 
			
		|||
fail_set_mode:
 | 
			
		||||
	set->crtc->enabled = save_enabled;
 | 
			
		||||
	count = 0;
 | 
			
		||||
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 | 
			
		||||
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 | 
			
		||||
		if (!connector->encoder)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		connector->encoder->crtc = save_crtcs[count++];
 | 
			
		||||
	}
 | 
			
		||||
fail_no_encoder:
 | 
			
		||||
	kfree(save_crtcs);
 | 
			
		||||
	count = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
 | 
			
		|||
	if (dev->driver->driver_features & DRIVER_GEM)
 | 
			
		||||
		drm_gem_release(dev, file_priv);
 | 
			
		||||
 | 
			
		||||
	if (dev->driver->driver_features & DRIVER_MODESET)
 | 
			
		||||
		drm_fb_release(file_priv);
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&dev->ctxlist_mutex);
 | 
			
		||||
	if (!list_empty(&dev->ctxlist)) {
 | 
			
		||||
		struct drm_ctx_list *pos, *n;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
 | 
			
		|||
 | 
			
		||||
	if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
 | 
			
		||||
			DRM_FILE_PAGE_OFFSET_SIZE)) {
 | 
			
		||||
		drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
 | 
			
		||||
		drm_ht_remove(&mm->offset_hash);
 | 
			
		||||
		drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -295,37 +295,39 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
 | 
			
		|||
		return -EBADF;
 | 
			
		||||
 | 
			
		||||
again:
 | 
			
		||||
	if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
 | 
			
		||||
		ret = -ENOMEM;
 | 
			
		||||
		goto err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spin_lock(&dev->object_name_lock);
 | 
			
		||||
	if (obj->name) {
 | 
			
		||||
		args->name = obj->name;
 | 
			
		||||
		spin_unlock(&dev->object_name_lock);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	if (!obj->name) {
 | 
			
		||||
		ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
 | 
			
		||||
					&obj->name);
 | 
			
		||||
		args->name = (uint64_t) obj->name;
 | 
			
		||||
		spin_unlock(&dev->object_name_lock);
 | 
			
		||||
 | 
			
		||||
		if (ret == -EAGAIN)
 | 
			
		||||
			goto again;
 | 
			
		||||
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
		if (ret != 0)
 | 
			
		||||
			goto err;
 | 
			
		||||
 | 
			
		||||
		/* Allocate a reference for the name table.  */
 | 
			
		||||
		drm_gem_object_reference(obj);
 | 
			
		||||
	} else {
 | 
			
		||||
		args->name = (uint64_t) obj->name;
 | 
			
		||||
		spin_unlock(&dev->object_name_lock);
 | 
			
		||||
		ret = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
	mutex_lock(&dev->struct_mutex);
 | 
			
		||||
	drm_gem_object_unreference(obj);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Leave the reference from the lookup around as the
 | 
			
		||||
	 * name table now holds one
 | 
			
		||||
	 */
 | 
			
		||||
	args->name = (uint64_t) obj->name;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Open an object using the global name, returning a handle and the size.
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
 | 
			
		|||
	spin_lock(&dev->object_name_lock);
 | 
			
		||||
	if (obj->name) {
 | 
			
		||||
		idr_remove(&dev->object_name_idr, obj->name);
 | 
			
		||||
		obj->name = 0;
 | 
			
		||||
		spin_unlock(&dev->object_name_lock);
 | 
			
		||||
		/*
 | 
			
		||||
		 * The object name held a reference to this object, drop
 | 
			
		||||
| 
						 | 
				
			
			@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_object_handle_free);
 | 
			
		||||
 | 
			
		||||
void drm_gem_vm_open(struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_gem_object *obj = vma->vm_private_data;
 | 
			
		||||
 | 
			
		||||
	drm_gem_object_reference(obj);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_vm_open);
 | 
			
		||||
 | 
			
		||||
void drm_gem_vm_close(struct vm_area_struct *vma)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_gem_object *obj = vma->vm_private_data;
 | 
			
		||||
	struct drm_device *dev = obj->dev;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&dev->struct_mutex);
 | 
			
		||||
	drm_gem_object_unreference(obj);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(drm_gem_vm_close);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * drm_gem_mmap - memory map routine for GEM objects
 | 
			
		||||
 * @filp: DRM file pointer
 | 
			
		||||
| 
						 | 
				
			
			@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 | 
			
		|||
#endif
 | 
			
		||||
	vma->vm_page_prot = __pgprot(prot);
 | 
			
		||||
 | 
			
		||||
	/* Take a ref for this mapping of the object, so that the fault
 | 
			
		||||
	 * handler can dereference the mmap offset's pointer to the object.
 | 
			
		||||
	 * This reference is cleaned up by the corresponding vm_close
 | 
			
		||||
	 * (which should happen whether the vma was created by this call, or
 | 
			
		||||
	 * by a vm_open due to mremap or partial unmap or whatever).
 | 
			
		||||
	 */
 | 
			
		||||
	drm_gem_object_reference(obj);
 | 
			
		||||
 | 
			
		||||
	vma->vm_file = filp;	/* Needed for drm_vm_open() */
 | 
			
		||||
	drm_vm_open_locked(vma);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
 | 
			
		|||
		dev_priv->ring.map.flags = 0;
 | 
			
		||||
		dev_priv->ring.map.mtrr = 0;
 | 
			
		||||
 | 
			
		||||
		drm_core_ioremap(&dev_priv->ring.map, dev);
 | 
			
		||||
		drm_core_ioremap_wc(&dev_priv->ring.map, dev);
 | 
			
		||||
 | 
			
		||||
		if (dev_priv->ring.map.handle == NULL) {
 | 
			
		||||
			i915_dma_cleanup(dev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include "drmP.h"
 | 
			
		||||
#include "drm.h"
 | 
			
		||||
#include "i915_drm.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +67,14 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 | 
			
		|||
 | 
			
		||||
	i915_save_state(dev);
 | 
			
		||||
 | 
			
		||||
	/* If KMS is active, we do the leavevt stuff here */
 | 
			
		||||
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 | 
			
		||||
		if (i915_gem_idle(dev))
 | 
			
		||||
			dev_err(&dev->pdev->dev,
 | 
			
		||||
				"GEM idle failed, resume may fail\n");
 | 
			
		||||
		drm_irq_uninstall(dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	intel_opregion_free(dev);
 | 
			
		||||
 | 
			
		||||
	if (state.event == PM_EVENT_SUSPEND) {
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +88,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 | 
			
		|||
 | 
			
		||||
static int i915_resume(struct drm_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_i915_private *dev_priv = dev->dev_private;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	pci_set_power_state(dev->pdev, PCI_D0);
 | 
			
		||||
	pci_restore_state(dev->pdev);
 | 
			
		||||
	if (pci_enable_device(dev->pdev))
 | 
			
		||||
| 
						 | 
				
			
			@ -89,11 +101,26 @@ static int i915_resume(struct drm_device *dev)
 | 
			
		|||
 | 
			
		||||
	intel_opregion_init(dev);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
	/* KMS EnterVT equivalent */
 | 
			
		||||
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 | 
			
		||||
		mutex_lock(&dev->struct_mutex);
 | 
			
		||||
		dev_priv->mm.suspended = 0;
 | 
			
		||||
 | 
			
		||||
		ret = i915_gem_init_ringbuffer(dev);
 | 
			
		||||
		if (ret != 0)
 | 
			
		||||
			ret = -1;
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
		drm_irq_install(dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct vm_operations_struct i915_gem_vm_ops = {
 | 
			
		||||
	.fault = i915_gem_fault,
 | 
			
		||||
	.open = drm_gem_vm_open,
 | 
			
		||||
	.close = drm_gem_vm_close,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct drm_driver driver = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,6 +184,8 @@ typedef struct drm_i915_private {
 | 
			
		|||
	unsigned int lvds_dither:1;
 | 
			
		||||
	unsigned int lvds_vbt:1;
 | 
			
		||||
	unsigned int int_crt_support:1;
 | 
			
		||||
	unsigned int lvds_use_ssc:1;
 | 
			
		||||
	int lvds_ssc_freq;
 | 
			
		||||
 | 
			
		||||
	struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
 | 
			
		||||
	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 | 
			
		||||
| 
						 | 
				
			
			@ -616,6 +618,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev);
 | 
			
		|||
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 | 
			
		||||
int i915_gem_do_init(struct drm_device *dev, unsigned long start,
 | 
			
		||||
		     unsigned long end);
 | 
			
		||||
int i915_gem_idle(struct drm_device *dev);
 | 
			
		||||
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 | 
			
		||||
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
 | 
			
		||||
				      int write);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,10 +34,6 @@
 | 
			
		|||
 | 
			
		||||
#define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
 | 
			
		||||
				  uint32_t read_domains,
 | 
			
		||||
				  uint32_t write_domain);
 | 
			
		||||
static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
 | 
			
		||||
static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 | 
			
		||||
static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
 | 
			
		||||
| 
						 | 
				
			
			@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 | 
			
		|||
	case -EAGAIN:
 | 
			
		||||
		return VM_FAULT_OOM;
 | 
			
		||||
	case -EFAULT:
 | 
			
		||||
	case -EBUSY:
 | 
			
		||||
		DRM_ERROR("can't insert pfn??  fault or busy...\n");
 | 
			
		||||
		return VM_FAULT_SIGBUS;
 | 
			
		||||
	default:
 | 
			
		||||
		return VM_FAULT_NOPAGE;
 | 
			
		||||
| 
						 | 
				
			
			@ -684,6 +678,30 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
i915_gem_free_mmap_offset(struct drm_gem_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = obj->dev;
 | 
			
		||||
	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 | 
			
		||||
	struct drm_gem_mm *mm = dev->mm_private;
 | 
			
		||||
	struct drm_map_list *list;
 | 
			
		||||
 | 
			
		||||
	list = &obj->map_list;
 | 
			
		||||
	drm_ht_remove_item(&mm->offset_hash, &list->hash);
 | 
			
		||||
 | 
			
		||||
	if (list->file_offset_node) {
 | 
			
		||||
		drm_mm_put_block(list->file_offset_node);
 | 
			
		||||
		list->file_offset_node = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (list->map) {
 | 
			
		||||
		drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
 | 
			
		||||
		list->map = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	obj_priv->mmap_offset = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * i915_gem_get_gtt_alignment - return required GTT alignment for an object
 | 
			
		||||
 * @obj: object to check
 | 
			
		||||
| 
						 | 
				
			
			@ -758,9 +776,12 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 | 
			
		|||
 | 
			
		||||
	if (!obj_priv->mmap_offset) {
 | 
			
		||||
		ret = i915_gem_create_mmap_offset(obj);
 | 
			
		||||
		if (ret)
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			drm_gem_object_unreference(obj);
 | 
			
		||||
			mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
			return ret;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args->offset = obj_priv->mmap_offset;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1030,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev)
 | 
			
		|||
	drm_i915_private_t *dev_priv = dev->dev_private;
 | 
			
		||||
	uint32_t seqno;
 | 
			
		||||
 | 
			
		||||
	if (!dev_priv->hw_status_page)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	seqno = i915_get_gem_seqno(dev);
 | 
			
		||||
 | 
			
		||||
	while (!list_empty(&dev_priv->mm.request_list)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1996,30 +2020,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
 | 
			
		|||
 *		drm_agp_chipset_flush
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
 | 
			
		||||
				  uint32_t read_domains,
 | 
			
		||||
				  uint32_t write_domain)
 | 
			
		||||
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device		*dev = obj->dev;
 | 
			
		||||
	struct drm_i915_gem_object	*obj_priv = obj->driver_private;
 | 
			
		||||
	uint32_t			invalidate_domains = 0;
 | 
			
		||||
	uint32_t			flush_domains = 0;
 | 
			
		||||
 | 
			
		||||
	BUG_ON(read_domains & I915_GEM_DOMAIN_CPU);
 | 
			
		||||
	BUG_ON(write_domain == I915_GEM_DOMAIN_CPU);
 | 
			
		||||
	BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
 | 
			
		||||
	BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
 | 
			
		||||
 | 
			
		||||
#if WATCH_BUF
 | 
			
		||||
	DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
 | 
			
		||||
		 __func__, obj,
 | 
			
		||||
		 obj->read_domains, read_domains,
 | 
			
		||||
		 obj->write_domain, write_domain);
 | 
			
		||||
		 obj->read_domains, obj->pending_read_domains,
 | 
			
		||||
		 obj->write_domain, obj->pending_write_domain);
 | 
			
		||||
#endif
 | 
			
		||||
	/*
 | 
			
		||||
	 * If the object isn't moving to a new write domain,
 | 
			
		||||
	 * let the object stay in multiple read domains
 | 
			
		||||
	 */
 | 
			
		||||
	if (write_domain == 0)
 | 
			
		||||
		read_domains |= obj->read_domains;
 | 
			
		||||
	if (obj->pending_write_domain == 0)
 | 
			
		||||
		obj->pending_read_domains |= obj->read_domains;
 | 
			
		||||
	else
 | 
			
		||||
		obj_priv->dirty = 1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2029,15 +2051,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
 | 
			
		|||
	 * any read domains which differ from the old
 | 
			
		||||
	 * write domain
 | 
			
		||||
	 */
 | 
			
		||||
	if (obj->write_domain && obj->write_domain != read_domains) {
 | 
			
		||||
	if (obj->write_domain &&
 | 
			
		||||
	    obj->write_domain != obj->pending_read_domains) {
 | 
			
		||||
		flush_domains |= obj->write_domain;
 | 
			
		||||
		invalidate_domains |= read_domains & ~obj->write_domain;
 | 
			
		||||
		invalidate_domains |=
 | 
			
		||||
			obj->pending_read_domains & ~obj->write_domain;
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	 * Invalidate any read caches which may have
 | 
			
		||||
	 * stale data. That is, any new read domains.
 | 
			
		||||
	 */
 | 
			
		||||
	invalidate_domains |= read_domains & ~obj->read_domains;
 | 
			
		||||
	invalidate_domains |= obj->pending_read_domains & ~obj->read_domains;
 | 
			
		||||
	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
 | 
			
		||||
#if WATCH_BUF
 | 
			
		||||
		DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
 | 
			
		||||
| 
						 | 
				
			
			@ -2046,9 +2070,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
 | 
			
		|||
		i915_gem_clflush_object(obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((write_domain | flush_domains) != 0)
 | 
			
		||||
		obj->write_domain = write_domain;
 | 
			
		||||
	obj->read_domains = read_domains;
 | 
			
		||||
	/* The actual obj->write_domain will be updated with
 | 
			
		||||
	 * pending_write_domain after we emit the accumulated flush for all
 | 
			
		||||
	 * of our domain changes in execbuffers (which clears objects'
 | 
			
		||||
	 * write_domains).  So if we have a current write domain that we
 | 
			
		||||
	 * aren't changing, set pending_write_domain to that.
 | 
			
		||||
	 */
 | 
			
		||||
	if (flush_domains == 0 && obj->pending_write_domain == 0)
 | 
			
		||||
		obj->pending_write_domain = obj->write_domain;
 | 
			
		||||
	obj->read_domains = obj->pending_read_domains;
 | 
			
		||||
 | 
			
		||||
	dev->invalidate_domains |= invalidate_domains;
 | 
			
		||||
	dev->flush_domains |= flush_domains;
 | 
			
		||||
| 
						 | 
				
			
			@ -2251,6 +2281,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
 | 
			
		|||
				  (int) reloc.offset,
 | 
			
		||||
				  reloc.read_domains,
 | 
			
		||||
				  reloc.write_domain);
 | 
			
		||||
			drm_gem_object_unreference(target_obj);
 | 
			
		||||
			i915_gem_object_unpin(obj);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2480,13 +2512,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 | 
			
		|||
	if (dev_priv->mm.wedged) {
 | 
			
		||||
		DRM_ERROR("Execbuf while wedged\n");
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return -EIO;
 | 
			
		||||
		ret = -EIO;
 | 
			
		||||
		goto pre_mutex_err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_priv->mm.suspended) {
 | 
			
		||||
		DRM_ERROR("Execbuf while VT-switched.\n");
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
		ret = -EBUSY;
 | 
			
		||||
		goto pre_mutex_err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Look up object handles */
 | 
			
		||||
| 
						 | 
				
			
			@ -2554,9 +2588,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 | 
			
		|||
		struct drm_gem_object *obj = object_list[i];
 | 
			
		||||
 | 
			
		||||
		/* Compute new gpu domains and update invalidate/flush */
 | 
			
		||||
		i915_gem_object_set_to_gpu_domain(obj,
 | 
			
		||||
						  obj->pending_read_domains,
 | 
			
		||||
						  obj->pending_write_domain);
 | 
			
		||||
		i915_gem_object_set_to_gpu_domain(obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i915_verify_inactive(dev, __FILE__, __LINE__);
 | 
			
		||||
| 
						 | 
				
			
			@ -2575,6 +2607,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 | 
			
		|||
			(void)i915_add_request(dev, dev->flush_domains);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < args->buffer_count; i++) {
 | 
			
		||||
		struct drm_gem_object *obj = object_list[i];
 | 
			
		||||
 | 
			
		||||
		obj->write_domain = obj->pending_write_domain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i915_verify_inactive(dev, __FILE__, __LINE__);
 | 
			
		||||
 | 
			
		||||
#if WATCH_COHERENCY
 | 
			
		||||
| 
						 | 
				
			
			@ -2632,6 +2670,16 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 | 
			
		|||
 | 
			
		||||
	i915_verify_inactive(dev, __FILE__, __LINE__);
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
	for (i = 0; i < pinned; i++)
 | 
			
		||||
		i915_gem_object_unpin(object_list[i]);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < args->buffer_count; i++)
 | 
			
		||||
		drm_gem_object_unreference(object_list[i]);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	if (!ret) {
 | 
			
		||||
		/* Copy the new buffer offsets back to the user's exec list. */
 | 
			
		||||
		ret = copy_to_user((struct drm_i915_relocation_entry __user *)
 | 
			
		||||
				   (uintptr_t) args->buffers_ptr,
 | 
			
		||||
| 
						 | 
				
			
			@ -2641,14 +2689,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 | 
			
		|||
			DRM_ERROR("failed to copy %d exec entries "
 | 
			
		||||
				  "back to user (%d)\n",
 | 
			
		||||
				  args->buffer_count, ret);
 | 
			
		||||
err:
 | 
			
		||||
	for (i = 0; i < pinned; i++)
 | 
			
		||||
		i915_gem_object_unpin(object_list[i]);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < args->buffer_count; i++)
 | 
			
		||||
		drm_gem_object_unreference(object_list[i]);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
pre_mutex_err:
 | 
			
		||||
	drm_free(object_list, sizeof(*object_list) * args->buffer_count,
 | 
			
		||||
| 
						 | 
				
			
			@ -2753,6 +2794,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 | 
			
		|||
	if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
 | 
			
		||||
		DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
 | 
			
		||||
			  args->handle);
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2833,6 +2875,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 | 
			
		|||
		return -EBADF;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Update the active list for the hardware's current position.
 | 
			
		||||
	 * Otherwise this only updates on a delayed timer or when irqs are
 | 
			
		||||
	 * actually unmasked, and our working set ends up being larger than
 | 
			
		||||
	 * required.
 | 
			
		||||
	 */
 | 
			
		||||
	i915_gem_retire_requests(dev);
 | 
			
		||||
 | 
			
		||||
	obj_priv = obj->driver_private;
 | 
			
		||||
	/* Don't count being on the flushing list against the object being
 | 
			
		||||
	 * done.  Otherwise, a buffer left on the flushing list but not getting
 | 
			
		||||
| 
						 | 
				
			
			@ -2885,9 +2934,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
 | 
			
		|||
void i915_gem_free_object(struct drm_gem_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_device *dev = obj->dev;
 | 
			
		||||
	struct drm_gem_mm *mm = dev->mm_private;
 | 
			
		||||
	struct drm_map_list *list;
 | 
			
		||||
	struct drm_map *map;
 | 
			
		||||
	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 | 
			
		||||
 | 
			
		||||
	while (obj_priv->pin_count > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -2898,19 +2944,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
 | 
			
		|||
 | 
			
		||||
	i915_gem_object_unbind(obj);
 | 
			
		||||
 | 
			
		||||
	list = &obj->map_list;
 | 
			
		||||
	drm_ht_remove_item(&mm->offset_hash, &list->hash);
 | 
			
		||||
 | 
			
		||||
	if (list->file_offset_node) {
 | 
			
		||||
		drm_mm_put_block(list->file_offset_node);
 | 
			
		||||
		list->file_offset_node = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	map = list->map;
 | 
			
		||||
	if (map) {
 | 
			
		||||
		drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
 | 
			
		||||
		list->map = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	i915_gem_free_mmap_offset(obj);
 | 
			
		||||
 | 
			
		||||
	drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
 | 
			
		||||
	drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
 | 
			
		||||
| 
						 | 
				
			
			@ -2949,7 +2983,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
int
 | 
			
		||||
i915_gem_idle(struct drm_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	drm_i915_private_t *dev_priv = dev->dev_private;
 | 
			
		||||
| 
						 | 
				
			
			@ -3095,6 +3129,7 @@ i915_gem_init_hws(struct drm_device *dev)
 | 
			
		|||
	if (dev_priv->hw_status_page == NULL) {
 | 
			
		||||
		DRM_ERROR("Failed to map status page.\n");
 | 
			
		||||
		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 | 
			
		||||
		i915_gem_object_unpin(obj);
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -3107,6 +3142,31 @@ i915_gem_init_hws(struct drm_device *dev)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
i915_gem_cleanup_hws(struct drm_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	drm_i915_private_t *dev_priv = dev->dev_private;
 | 
			
		||||
	struct drm_gem_object *obj;
 | 
			
		||||
	struct drm_i915_gem_object *obj_priv;
 | 
			
		||||
 | 
			
		||||
	if (dev_priv->hws_obj == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	obj = dev_priv->hws_obj;
 | 
			
		||||
	obj_priv = obj->driver_private;
 | 
			
		||||
 | 
			
		||||
	kunmap(obj_priv->page_list[0]);
 | 
			
		||||
	i915_gem_object_unpin(obj);
 | 
			
		||||
	drm_gem_object_unreference(obj);
 | 
			
		||||
	dev_priv->hws_obj = NULL;
 | 
			
		||||
 | 
			
		||||
	memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 | 
			
		||||
	dev_priv->hw_status_page = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Write high address into HWS_PGA when disabling. */
 | 
			
		||||
	I915_WRITE(HWS_PGA, 0x1ffff000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
i915_gem_init_ringbuffer(struct drm_device *dev)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -3124,6 +3184,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
 | 
			
		|||
	obj = drm_gem_object_alloc(dev, 128 * 1024);
 | 
			
		||||
	if (obj == NULL) {
 | 
			
		||||
		DRM_ERROR("Failed to allocate ringbuffer\n");
 | 
			
		||||
		i915_gem_cleanup_hws(dev);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	obj_priv = obj->driver_private;
 | 
			
		||||
| 
						 | 
				
			
			@ -3131,6 +3192,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
 | 
			
		|||
	ret = i915_gem_object_pin(obj, 4096);
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		i915_gem_cleanup_hws(dev);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3148,7 +3210,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
 | 
			
		|||
	if (ring->map.handle == NULL) {
 | 
			
		||||
		DRM_ERROR("Failed to map ringbuffer.\n");
 | 
			
		||||
		memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
 | 
			
		||||
		i915_gem_object_unpin(obj);
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		i915_gem_cleanup_hws(dev);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	ring->ring_obj = obj;
 | 
			
		||||
| 
						 | 
				
			
			@ -3228,20 +3292,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
 | 
			
		|||
	dev_priv->ring.ring_obj = NULL;
 | 
			
		||||
	memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
 | 
			
		||||
 | 
			
		||||
	if (dev_priv->hws_obj != NULL) {
 | 
			
		||||
		struct drm_gem_object *obj = dev_priv->hws_obj;
 | 
			
		||||
		struct drm_i915_gem_object *obj_priv = obj->driver_private;
 | 
			
		||||
 | 
			
		||||
		kunmap(obj_priv->page_list[0]);
 | 
			
		||||
		i915_gem_object_unpin(obj);
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		dev_priv->hws_obj = NULL;
 | 
			
		||||
		memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
 | 
			
		||||
		dev_priv->hw_status_page = NULL;
 | 
			
		||||
 | 
			
		||||
		/* Write high address into HWS_PGA when disabling. */
 | 
			
		||||
		I915_WRITE(HWS_PGA, 0x1ffff000);
 | 
			
		||||
	}
 | 
			
		||||
	i915_gem_cleanup_hws(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 | 
			
		|||
	}
 | 
			
		||||
	obj_priv->stride = args->stride;
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	drm_gem_object_unreference(obj);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
 | 
			
		|||
		DRM_ERROR("unknown tiling mode\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	drm_gem_object_unreference(obj);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
 | 
			
		|||
	if (general) {
 | 
			
		||||
		dev_priv->int_tv_support = general->int_tv_support;
 | 
			
		||||
		dev_priv->int_crt_support = general->int_crt_support;
 | 
			
		||||
		dev_priv->lvds_use_ssc = general->enable_ssc;
 | 
			
		||||
 | 
			
		||||
		if (dev_priv->lvds_use_ssc) {
 | 
			
		||||
		  if (IS_I855(dev_priv->dev))
 | 
			
		||||
		    dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
 | 
			
		||||
		  else
 | 
			
		||||
		    dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,12 +90,12 @@ typedef struct {
 | 
			
		|||
#define I9XX_DOT_MAX		 400000
 | 
			
		||||
#define I9XX_VCO_MIN		1400000
 | 
			
		||||
#define I9XX_VCO_MAX		2800000
 | 
			
		||||
#define I9XX_N_MIN		      3
 | 
			
		||||
#define I9XX_N_MAX		      8
 | 
			
		||||
#define I9XX_N_MIN		      1
 | 
			
		||||
#define I9XX_N_MAX		      6
 | 
			
		||||
#define I9XX_M_MIN		     70
 | 
			
		||||
#define I9XX_M_MAX		    120
 | 
			
		||||
#define I9XX_M1_MIN		     10
 | 
			
		||||
#define I9XX_M1_MAX		     20
 | 
			
		||||
#define I9XX_M1_MAX		     22
 | 
			
		||||
#define I9XX_M2_MIN		      5
 | 
			
		||||
#define I9XX_M2_MAX		      9
 | 
			
		||||
#define I9XX_P_SDVO_DAC_MIN	      5
 | 
			
		||||
| 
						 | 
				
			
			@ -189,9 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
 | 
			
		|||
	return limit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
 | 
			
		||||
 | 
			
		||||
static void i8xx_clock(int refclk, intel_clock_t *clock)
 | 
			
		||||
static void intel_clock(int refclk, intel_clock_t *clock)
 | 
			
		||||
{
 | 
			
		||||
	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
 | 
			
		||||
	clock->p = clock->p1 * clock->p2;
 | 
			
		||||
| 
						 | 
				
			
			@ -199,25 +197,6 @@ static void i8xx_clock(int refclk, intel_clock_t *clock)
 | 
			
		|||
	clock->dot = clock->vco / clock->p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
 | 
			
		||||
 | 
			
		||||
static void i9xx_clock(int refclk, intel_clock_t *clock)
 | 
			
		||||
{
 | 
			
		||||
	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
 | 
			
		||||
	clock->p = clock->p1 * clock->p2;
 | 
			
		||||
	clock->vco = refclk * clock->m / (clock->n + 2);
 | 
			
		||||
	clock->dot = clock->vco / clock->p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void intel_clock(struct drm_device *dev, int refclk,
 | 
			
		||||
			intel_clock_t *clock)
 | 
			
		||||
{
 | 
			
		||||
	if (IS_I9XX(dev))
 | 
			
		||||
		i9xx_clock (refclk, clock);
 | 
			
		||||
	else
 | 
			
		||||
		i8xx_clock (refclk, clock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns whether any output on the specified pipe is of the specified type
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
 | 
			
		||||
#define INTELPllInvalid(s)   do { DRM_DEBUG(s); return false; } while (0)
 | 
			
		||||
/**
 | 
			
		||||
 * Returns whether the given set of divisors are valid for a given refclk with
 | 
			
		||||
 * the given connectors.
 | 
			
		||||
| 
						 | 
				
			
			@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
 | 
			
		|||
				     clock.p1 <= limit->p1.max; clock.p1++) {
 | 
			
		||||
					int this_err;
 | 
			
		||||
 | 
			
		||||
					intel_clock(dev, refclk, &clock);
 | 
			
		||||
					intel_clock(refclk, &clock);
 | 
			
		||||
 | 
			
		||||
					if (!intel_PLL_is_valid(crtc, &clock))
 | 
			
		||||
						continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev)
 | 
			
		|||
	udelay(20000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
static int
 | 
			
		||||
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		||||
		    struct drm_framebuffer *old_fb)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		|||
	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
 | 
			
		||||
	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
 | 
			
		||||
	u32 dspcntr, alignment;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/* no fb bound */
 | 
			
		||||
	if (!crtc->fb) {
 | 
			
		||||
		DRM_DEBUG("No FB bound\n");
 | 
			
		||||
		return;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (pipe) {
 | 
			
		||||
	case 0:
 | 
			
		||||
	case 1:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	intel_fb = to_intel_framebuffer(crtc->fb);
 | 
			
		||||
| 
						 | 
				
			
			@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		|||
		alignment = 64 * 1024;
 | 
			
		||||
		break;
 | 
			
		||||
	case I915_TILING_X:
 | 
			
		||||
		if (IS_I9XX(dev))
 | 
			
		||||
			alignment = 1024 * 1024;
 | 
			
		||||
		else
 | 
			
		||||
			alignment = 512 * 1024;
 | 
			
		||||
		/* pin() will align the object as required by fence */
 | 
			
		||||
		alignment = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case I915_TILING_Y:
 | 
			
		||||
		/* FIXME: Is this true? */
 | 
			
		||||
		DRM_ERROR("Y tiled not allowed for scan out buffers\n");
 | 
			
		||||
		return;
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	default:
 | 
			
		||||
		BUG();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (i915_gem_object_pin(intel_fb->obj, alignment))
 | 
			
		||||
		return;
 | 
			
		||||
	mutex_lock(&dev->struct_mutex);
 | 
			
		||||
	ret = i915_gem_object_pin(intel_fb->obj, alignment);
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
 | 
			
		||||
 | 
			
		||||
	Start = obj_priv->gtt_offset;
 | 
			
		||||
	Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 | 
			
		||||
 | 
			
		||||
	I915_WRITE(dspstride, crtc->fb->pitch);
 | 
			
		||||
	ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
		i915_gem_object_unpin(intel_fb->obj);
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dspcntr = I915_READ(dspcntr_reg);
 | 
			
		||||
	/* Mask out pixel format bits in case we change it */
 | 
			
		||||
| 
						 | 
				
			
			@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		|||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		DRM_ERROR("Unknown color depth\n");
 | 
			
		||||
		return;
 | 
			
		||||
		i915_gem_object_unpin(intel_fb->obj);
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	I915_WRITE(dspcntr_reg, dspcntr);
 | 
			
		||||
 | 
			
		||||
	Start = obj_priv->gtt_offset;
 | 
			
		||||
	Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 | 
			
		||||
 | 
			
		||||
	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
 | 
			
		||||
	I915_WRITE(dspstride, crtc->fb->pitch);
 | 
			
		||||
	if (IS_I965G(dev)) {
 | 
			
		||||
		I915_WRITE(dspbase, Offset);
 | 
			
		||||
		I915_READ(dspbase);
 | 
			
		||||
| 
						 | 
				
			
			@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 | 
			
		|||
		intel_fb = to_intel_framebuffer(old_fb);
 | 
			
		||||
		i915_gem_object_unpin(intel_fb->obj);
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	if (!dev->primary->master)
 | 
			
		||||
		return;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	master_priv = dev->primary->master->driver_priv;
 | 
			
		||||
	if (!master_priv->sarea_priv)
 | 
			
		||||
		return;
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	switch (pipe) {
 | 
			
		||||
	case 0:
 | 
			
		||||
		master_priv->sarea_priv->pipeA_x = x;
 | 
			
		||||
		master_priv->sarea_priv->pipeA_y = y;
 | 
			
		||||
		break;
 | 
			
		||||
	case 1:
 | 
			
		||||
	if (pipe) {
 | 
			
		||||
		master_priv->sarea_priv->pipeB_x = x;
 | 
			
		||||
		master_priv->sarea_priv->pipeB_y = y;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
 | 
			
		||||
		break;
 | 
			
		||||
	} else {
 | 
			
		||||
		master_priv->sarea_priv->pipeA_x = x;
 | 
			
		||||
		master_priv->sarea_priv->pipeA_y = y;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -708,7 +702,7 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
 | 
			
		|||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		||||
static int intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		||||
			       struct drm_display_mode *mode,
 | 
			
		||||
			       struct drm_display_mode *adjusted_mode,
 | 
			
		||||
			       int x, int y,
 | 
			
		||||
| 
						 | 
				
			
			@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
 | 
			
		||||
	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
 | 
			
		||||
	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
 | 
			
		||||
	int refclk;
 | 
			
		||||
	int refclk, num_outputs = 0;
 | 
			
		||||
	intel_clock_t clock;
 | 
			
		||||
	u32 dpll = 0, fp = 0, dspcntr, pipeconf;
 | 
			
		||||
	bool ok, is_sdvo = false, is_dvo = false;
 | 
			
		||||
	bool is_crt = false, is_lvds = false, is_tv = false;
 | 
			
		||||
	struct drm_mode_config *mode_config = &dev->mode_config;
 | 
			
		||||
	struct drm_connector *connector;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	drm_vblank_pre_modeset(dev, pipe);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
			is_crt = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		num_outputs++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (IS_I9XX(dev)) {
 | 
			
		||||
	if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
 | 
			
		||||
		refclk = dev_priv->lvds_ssc_freq * 1000;
 | 
			
		||||
		DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
 | 
			
		||||
	} else if (IS_I9XX(dev)) {
 | 
			
		||||
		refclk = 96000;
 | 
			
		||||
	} else {
 | 
			
		||||
		refclk = 48000;
 | 
			
		||||
| 
						 | 
				
			
			@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
	ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
 | 
			
		||||
	if (!ok) {
 | 
			
		||||
		DRM_ERROR("Couldn't find PLL settings for mode!\n");
 | 
			
		||||
		return;
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 | 
			
		||||
| 
						 | 
				
			
			@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_tv) {
 | 
			
		||||
	if (is_sdvo && is_tv)
 | 
			
		||||
		dpll |= PLL_REF_INPUT_TVCLKINBC;
 | 
			
		||||
	else if (is_tv)
 | 
			
		||||
		/* XXX: just matching BIOS for now */
 | 
			
		||||
		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
 | 
			
		||||
		dpll |= 3;
 | 
			
		||||
	}
 | 
			
		||||
	else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
 | 
			
		||||
		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 | 
			
		||||
	else
 | 
			
		||||
		dpll |= PLL_REF_INPUT_DREFCLK;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
 | 
			
		|||
	I915_WRITE(dspcntr_reg, dspcntr);
 | 
			
		||||
 | 
			
		||||
	/* Flush the plane changes */
 | 
			
		||||
	intel_pipe_set_base(crtc, x, y, old_fb);
 | 
			
		||||
	ret = intel_pipe_set_base(crtc, x, y, old_fb);
 | 
			
		||||
	if (ret != 0)
 | 
			
		||||
	    return ret;
 | 
			
		||||
 | 
			
		||||
	drm_vblank_post_modeset(dev, pipe);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Loads the palette/gamma unit for the CRTC with the prepared values */
 | 
			
		||||
| 
						 | 
				
			
			@ -1001,6 +1008,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 | 
			
		|||
		temp = CURSOR_MODE_DISABLE;
 | 
			
		||||
		addr = 0;
 | 
			
		||||
		bo = NULL;
 | 
			
		||||
		mutex_lock(&dev->struct_mutex);
 | 
			
		||||
		goto finish;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1023,18 +1031,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* we only need to pin inside GTT if cursor is non-phy */
 | 
			
		||||
	mutex_lock(&dev->struct_mutex);
 | 
			
		||||
	if (!dev_priv->cursor_needs_physical) {
 | 
			
		||||
		ret = i915_gem_object_pin(bo, PAGE_SIZE);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			DRM_ERROR("failed to pin cursor bo\n");
 | 
			
		||||
			goto fail;
 | 
			
		||||
			goto fail_locked;
 | 
			
		||||
		}
 | 
			
		||||
		addr = obj_priv->gtt_offset;
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			DRM_ERROR("failed to attach phys object\n");
 | 
			
		||||
			goto fail;
 | 
			
		||||
			goto fail_locked;
 | 
			
		||||
		}
 | 
			
		||||
		addr = obj_priv->phys_obj->handle->busaddr;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1054,10 +1063,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 | 
			
		|||
				i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
 | 
			
		||||
		} else
 | 
			
		||||
			i915_gem_object_unpin(intel_crtc->cursor_bo);
 | 
			
		||||
		mutex_lock(&dev->struct_mutex);
 | 
			
		||||
		drm_gem_object_unreference(intel_crtc->cursor_bo);
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
	}
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
 | 
			
		||||
	intel_crtc->cursor_addr = addr;
 | 
			
		||||
	intel_crtc->cursor_bo = bo;
 | 
			
		||||
| 
						 | 
				
			
			@ -1065,6 +1073,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 | 
			
		|||
	return 0;
 | 
			
		||||
fail:
 | 
			
		||||
	mutex_lock(&dev->struct_mutex);
 | 
			
		||||
fail_locked:
 | 
			
		||||
	drm_gem_object_unreference(bo);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
	return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -1292,7 +1301,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		/* XXX: Handle the 100Mhz refclk */
 | 
			
		||||
		i9xx_clock(96000, &clock);
 | 
			
		||||
		intel_clock(96000, &clock);
 | 
			
		||||
	} else {
 | 
			
		||||
		bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1304,9 +1313,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 | 
			
		|||
			if ((dpll & PLL_REF_INPUT_MASK) ==
 | 
			
		||||
			    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
 | 
			
		||||
				/* XXX: might not be 66MHz */
 | 
			
		||||
				i8xx_clock(66000, &clock);
 | 
			
		||||
				intel_clock(66000, &clock);
 | 
			
		||||
			} else
 | 
			
		||||
				i8xx_clock(48000, &clock);
 | 
			
		||||
				intel_clock(48000, &clock);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (dpll & PLL_P1_DIVIDE_BY_TWO)
 | 
			
		||||
				clock.p1 = 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1319,7 +1328,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 | 
			
		|||
			else
 | 
			
		||||
				clock.p2 = 2;
 | 
			
		||||
 | 
			
		||||
			i8xx_clock(48000, &clock);
 | 
			
		||||
			intel_clock(48000, &clock);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1598,7 +1607,9 @@ intel_user_framebuffer_create(struct drm_device *dev,
 | 
			
		|||
 | 
			
		||||
	ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		mutex_lock(&dev->struct_mutex);
 | 
			
		||||
		drm_gem_object_unreference(obj);
 | 
			
		||||
		mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
 | 
			
		|||
	ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		DRM_ERROR("failed to allocate fb.\n");
 | 
			
		||||
		goto out_unref;
 | 
			
		||||
		goto out_unpin;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
 | 
			
		||||
| 
						 | 
				
			
			@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
 | 
			
		|||
	info = framebuffer_alloc(sizeof(struct intelfb_par), device);
 | 
			
		||||
	if (!info) {
 | 
			
		||||
		ret = -ENOMEM;
 | 
			
		||||
		goto out_unref;
 | 
			
		||||
		goto out_unpin;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	par = info->par;
 | 
			
		||||
| 
						 | 
				
			
			@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
 | 
			
		|||
				       size);
 | 
			
		||||
	if (!info->screen_base) {
 | 
			
		||||
		ret = -ENOSPC;
 | 
			
		||||
		goto out_unref;
 | 
			
		||||
		goto out_unpin;
 | 
			
		||||
	}
 | 
			
		||||
	info->screen_size = size;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
 | 
			
		|||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
out_unpin:
 | 
			
		||||
	i915_gem_object_unpin(fbo);
 | 
			
		||||
out_unref:
 | 
			
		||||
	drm_gem_object_unreference(fbo);
 | 
			
		||||
	mutex_unlock(&dev->struct_mutex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
 | 
			
		|||
		if (dev_priv->panel_fixed_mode) {
 | 
			
		||||
			dev_priv->panel_fixed_mode->type |=
 | 
			
		||||
				DRM_MODE_TYPE_PREFERRED;
 | 
			
		||||
			drm_mode_probed_add(connector,
 | 
			
		||||
					    dev_priv->panel_fixed_mode);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
 | 
			
		|||
 | 
			
		||||
#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
 | 
			
		||||
/** Mapping of command numbers to names, for debug output */
 | 
			
		||||
const static struct _sdvo_cmd_name {
 | 
			
		||||
static const struct _sdvo_cmd_name {
 | 
			
		||||
	u8 cmd;
 | 
			
		||||
	char *name;
 | 
			
		||||
} sdvo_cmd_names[] = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -411,7 +411,7 @@ struct tv_mode {
 | 
			
		|||
 * These values account for -1s required.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const static struct tv_mode tv_modes[] = {
 | 
			
		||||
static const struct tv_mode tv_modes[] = {
 | 
			
		||||
	{
 | 
			
		||||
		.name		= "NTSC-M",
 | 
			
		||||
		.clock		= 107520,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 | 
			
		||||
				       drm_radeon_private_t * dev_priv)
 | 
			
		||||
				       drm_radeon_private_t *dev_priv,
 | 
			
		||||
				       struct drm_file *file_priv)
 | 
			
		||||
{
 | 
			
		||||
	struct drm_radeon_master_private *master_priv;
 | 
			
		||||
	u32 ring_start, cur_read_ptr;
 | 
			
		||||
	u32 tmp;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 | 
			
		|||
	dev_priv->scratch[2] = 0;
 | 
			
		||||
	RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
 | 
			
		||||
 | 
			
		||||
	/* reset sarea copies of these */
 | 
			
		||||
	master_priv = file_priv->master->driver_priv;
 | 
			
		||||
	if (master_priv->sarea_priv) {
 | 
			
		||||
		master_priv->sarea_priv->last_frame = 0;
 | 
			
		||||
		master_priv->sarea_priv->last_dispatch = 0;
 | 
			
		||||
		master_priv->sarea_priv->last_clear = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	radeon_do_wait_for_idle(dev_priv);
 | 
			
		||||
 | 
			
		||||
	/* Sync everything up */
 | 
			
		||||
| 
						 | 
				
			
			@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	radeon_cp_load_microcode(dev_priv);
 | 
			
		||||
	radeon_cp_init_ring_buffer(dev, dev_priv);
 | 
			
		||||
	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 | 
			
		||||
 | 
			
		||||
	dev_priv->last_buf = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
 | 
			
		|||
 *
 | 
			
		||||
 * Charl P. Botha <http://cpbotha.net>
 | 
			
		||||
 */
 | 
			
		||||
static int radeon_do_resume_cp(struct drm_device * dev)
 | 
			
		||||
static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
 | 
			
		||||
{
 | 
			
		||||
	drm_radeon_private_t *dev_priv = dev->dev_private;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	radeon_cp_load_microcode(dev_priv);
 | 
			
		||||
	radeon_cp_init_ring_buffer(dev, dev_priv);
 | 
			
		||||
	radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 | 
			
		||||
 | 
			
		||||
	radeon_do_engine_reset(dev);
 | 
			
		||||
	radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
 | 
			
		|||
 */
 | 
			
		||||
int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	return radeon_do_resume_cp(dev);
 | 
			
		||||
	return radeon_do_resume_cp(dev, file_priv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,10 +79,11 @@ static struct i2c_algo_bit_data ioc_data = {
 | 
			
		|||
	.getsda		= ioc_getsda,
 | 
			
		||||
	.getscl		= ioc_getscl,
 | 
			
		||||
	.udelay		= 80,
 | 
			
		||||
	.timeout	= 100
 | 
			
		||||
	.timeout	= HZ,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct i2c_adapter ioc_ops = {
 | 
			
		||||
	.nr			= 0,
 | 
			
		||||
	.algo_data		= &ioc_data,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +91,7 @@ static int __init i2c_ioc_init(void)
 | 
			
		|||
{
 | 
			
		||||
	force_ones = FORCE_ONES | SCL | SDA;
 | 
			
		||||
 | 
			
		||||
	return i2c_bit_add_bus(&ioc_ops);
 | 
			
		||||
	return i2c_bit_add_numbered_bus(&ioc_ops);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(i2c_ioc_init);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,7 +72,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
 | 
			
		|||
{
 | 
			
		||||
	int timeout = 500;
 | 
			
		||||
 | 
			
		||||
	while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
 | 
			
		||||
	while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
 | 
			
		||||
		udelay(1);
 | 
			
		||||
 | 
			
		||||
	if (!timeout) {
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
 | 
			
		|||
{
 | 
			
		||||
	int timeout = 500;
 | 
			
		||||
 | 
			
		||||
	while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
 | 
			
		||||
	while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
 | 
			
		||||
		udelay(1);
 | 
			
		||||
 | 
			
		||||
	if (!timeout) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
 | 
			
		|||
	drv_data->algo_data.getsda = ixp2000_bit_getsda;
 | 
			
		||||
	drv_data->algo_data.getscl = ixp2000_bit_getscl;
 | 
			
		||||
	drv_data->algo_data.udelay = 6;
 | 
			
		||||
	drv_data->algo_data.timeout = 100;
 | 
			
		||||
	drv_data->algo_data.timeout = HZ;
 | 
			
		||||
 | 
			
		||||
	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
 | 
			
		||||
		sizeof(drv_data->adapter.name));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -644,7 +644,7 @@ static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
 | 
			
		|||
 | 
			
		||||
	i2c_pxa_start_message(i2c);
 | 
			
		||||
 | 
			
		||||
	while (timeout-- && i2c->msg_num > 0) {
 | 
			
		||||
	while (i2c->msg_num > 0 && --timeout) {
 | 
			
		||||
		i2c_pxa_handler(0, i2c);
 | 
			
		||||
		udelay(10);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
 | 
			
		|||
	.getsda		= scx200_i2c_getsda,
 | 
			
		||||
	.getscl		= scx200_i2c_getscl,
 | 
			
		||||
	.udelay		= 10,
 | 
			
		||||
	.timeout	= 100,
 | 
			
		||||
	.timeout	= HZ,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct i2c_adapter scx200_i2c_ops = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1831,7 +1831,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
 | 
			
		|||
	case I2C_SMBUS_QUICK:
 | 
			
		||||
		msg[0].len = 0;
 | 
			
		||||
		/* Special case: The read/write field is used as data */
 | 
			
		||||
		msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
 | 
			
		||||
		msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
 | 
			
		||||
					I2C_M_RD : 0);
 | 
			
		||||
		num = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case I2C_SMBUS_BYTE:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@
 | 
			
		|||
#include <linux/i2c.h>
 | 
			
		||||
#include <linux/i2c-dev.h>
 | 
			
		||||
#include <linux/smp_lock.h>
 | 
			
		||||
#include <linux/jiffies.h>
 | 
			
		||||
#include <asm/uaccess.h>
 | 
			
		||||
 | 
			
		||||
static struct i2c_driver i2cdev_driver;
 | 
			
		||||
| 
						 | 
				
			
			@ -422,7 +423,10 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 | 
			
		|||
		client->adapter->retries = arg;
 | 
			
		||||
		break;
 | 
			
		||||
	case I2C_TIMEOUT:
 | 
			
		||||
		client->adapter->timeout = arg;
 | 
			
		||||
		/* For historical reasons, user-space sets the timeout
 | 
			
		||||
		 * value in units of 10 ms.
 | 
			
		||||
		 */
 | 
			
		||||
		client->adapter->timeout = msecs_to_jiffies(arg * 10);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* NOTE:  returning a fault code here could cause trouble
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
 | 
			
		||||
#include <asm/types.h>
 | 
			
		||||
 | 
			
		||||
struct file;
 | 
			
		||||
struct pci_dev;
 | 
			
		||||
struct scatterlist;
 | 
			
		||||
struct vm_area_struct;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1314,6 +1314,7 @@ EXPORT_SYMBOL(hpsb_make_lock64packet);
 | 
			
		|||
EXPORT_SYMBOL(hpsb_make_phypacket);
 | 
			
		||||
EXPORT_SYMBOL(hpsb_read);
 | 
			
		||||
EXPORT_SYMBOL(hpsb_write);
 | 
			
		||||
EXPORT_SYMBOL(hpsb_lock);
 | 
			
		||||
EXPORT_SYMBOL(hpsb_packet_success);
 | 
			
		||||
 | 
			
		||||
/** highlevel.c **/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -501,8 +501,6 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		|||
	if (length == 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
 | 
			
		||||
 | 
			
		||||
	packet = hpsb_make_readpacket(host, node, addr, length);
 | 
			
		||||
 | 
			
		||||
	if (!packet) {
 | 
			
		||||
| 
						 | 
				
			
			@ -550,8 +548,6 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		|||
	if (length == 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
 | 
			
		||||
 | 
			
		||||
	packet = hpsb_make_writepacket(host, node, addr, buffer, length);
 | 
			
		||||
 | 
			
		||||
	if (!packet)
 | 
			
		||||
| 
						 | 
				
			
			@ -570,3 +566,30 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		|||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		||||
	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
 | 
			
		||||
{
 | 
			
		||||
	struct hpsb_packet *packet;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
 | 
			
		||||
	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
 | 
			
		||||
	if (!packet)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	packet->generation = generation;
 | 
			
		||||
	retval = hpsb_send_packet_and_wait(packet);
 | 
			
		||||
	if (retval < 0)
 | 
			
		||||
		goto hpsb_lock_fail;
 | 
			
		||||
 | 
			
		||||
	retval = hpsb_packet_success(packet);
 | 
			
		||||
 | 
			
		||||
	if (retval == 0)
 | 
			
		||||
		*data = packet->data[0];
 | 
			
		||||
 | 
			
		||||
hpsb_lock_fail:
 | 
			
		||||
	hpsb_free_tlabel(packet);
 | 
			
		||||
	hpsb_free_packet(packet);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		|||
	      u64 addr, quadlet_t *buffer, size_t length);
 | 
			
		||||
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		||||
	       u64 addr, quadlet_t *buffer, size_t length);
 | 
			
		||||
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
 | 
			
		||||
	      u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
 | 
			
		||||
 | 
			
		||||
#ifdef HPSB_DEBUG_TLABELS
 | 
			
		||||
extern spinlock_t hpsb_tlabel_lock;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#define IEEE1394_ISO_H
 | 
			
		||||
 | 
			
		||||
#include <linux/spinlock_types.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <asm/atomic.h>
 | 
			
		||||
#include <asm/types.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -971,6 +971,9 @@ static struct unit_directory *nodemgr_process_unit_directory
 | 
			
		|||
	ud->ud_kv = ud_kv;
 | 
			
		||||
	ud->id = (*id)++;
 | 
			
		||||
 | 
			
		||||
	/* inherit vendor_id from root directory if none exists in unit dir */
 | 
			
		||||
	ud->vendor_id = ne->vendor_id;
 | 
			
		||||
 | 
			
		||||
	csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
 | 
			
		||||
		switch (kv->key.id) {
 | 
			
		||||
		case CSR1212_KV_ID_VENDOR:
 | 
			
		||||
| 
						 | 
				
			
			@ -1265,7 +1268,8 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
 | 
			
		|||
		csr1212_destroy_csr(csr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Mark the node current */
 | 
			
		||||
	/* Finally, mark the node current */
 | 
			
		||||
	smp_wmb();
 | 
			
		||||
	ne->generation = generation;
 | 
			
		||||
 | 
			
		||||
	if (ne->in_limbo) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1798,7 +1802,7 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
 | 
			
		|||
{
 | 
			
		||||
	packet->host = ne->host;
 | 
			
		||||
	packet->generation = ne->generation;
 | 
			
		||||
	barrier();
 | 
			
		||||
	smp_rmb();
 | 
			
		||||
	packet->node_id = ne->nodeid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1807,7 +1811,7 @@ int hpsb_node_write(struct node_entry *ne, u64 addr,
 | 
			
		|||
{
 | 
			
		||||
	unsigned int generation = ne->generation;
 | 
			
		||||
 | 
			
		||||
	barrier();
 | 
			
		||||
	smp_rmb();
 | 
			
		||||
	return hpsb_write(ne->host, ne->nodeid, generation,
 | 
			
		||||
			  addr, buffer, length);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,9 +21,11 @@
 | 
			
		|||
#define _IEEE1394_NODEMGR_H
 | 
			
		||||
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
#include <asm/types.h>
 | 
			
		||||
 | 
			
		||||
#include "ieee1394_core.h"
 | 
			
		||||
#include "ieee1394_transactions.h"
 | 
			
		||||
#include "ieee1394_types.h"
 | 
			
		||||
 | 
			
		||||
struct csr1212_csr;
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +156,22 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
 | 
			
		|||
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
 | 
			
		||||
int hpsb_node_write(struct node_entry *ne, u64 addr,
 | 
			
		||||
		    quadlet_t *buffer, size_t length);
 | 
			
		||||
static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
 | 
			
		||||
				 quadlet_t *buffer, size_t length)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int g = ne->generation;
 | 
			
		||||
 | 
			
		||||
	smp_rmb();
 | 
			
		||||
	return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
 | 
			
		||||
}
 | 
			
		||||
static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
 | 
			
		||||
				 quadlet_t *buffer, quadlet_t arg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int g = ne->generation;
 | 
			
		||||
 | 
			
		||||
	smp_rmb();
 | 
			
		||||
	return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
 | 
			
		||||
}
 | 
			
		||||
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
 | 
			
		||||
 | 
			
		||||
int init_ieee1394_nodemgr(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ void memcpy_toshmem(int card, void *dest, const void *src, size_t n)
 | 
			
		|||
	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 | 
			
		||||
	pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename,
 | 
			
		||||
		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
 | 
			
		||||
	pr_debug("%s: copying %d bytes from %#lx to %#lx\n",
 | 
			
		||||
	pr_debug("%s: copying %zu bytes from %#lx to %#lx\n",
 | 
			
		||||
		sc_adapter[card]->devicename, n,
 | 
			
		||||
		(unsigned long) src,
 | 
			
		||||
		sc_adapter[card]->rambase + ((unsigned long) dest %0x4000));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,10 @@ comment "Supported SDMC DM1105 Adapters"
 | 
			
		|||
	depends on DVB_CORE && PCI && I2C
 | 
			
		||||
source "drivers/media/dvb/dm1105/Kconfig"
 | 
			
		||||
 | 
			
		||||
comment "Supported FireWire (IEEE 1394) Adapters"
 | 
			
		||||
	depends on DVB_CORE && IEEE1394
 | 
			
		||||
source "drivers/media/dvb/firewire/Kconfig"
 | 
			
		||||
 | 
			
		||||
comment "Supported DVB Frontends"
 | 
			
		||||
	depends on DVB_CORE
 | 
			
		||||
source "drivers/media/dvb/frontends/Kconfig"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,3 +3,5 @@
 | 
			
		|||
#
 | 
			
		||||
 | 
			
		||||
obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_DVB_FIREDTV)	+= firewire/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								drivers/media/dvb/firewire/Kconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								drivers/media/dvb/firewire/Kconfig
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
config DVB_FIREDTV
 | 
			
		||||
	tristate "FireDTV and FloppyDTV"
 | 
			
		||||
	depends on DVB_CORE && IEEE1394
 | 
			
		||||
	help
 | 
			
		||||
	  Support for DVB receivers from Digital Everywhere
 | 
			
		||||
	  which are connected via IEEE 1394 (FireWire).
 | 
			
		||||
 | 
			
		||||
	  These devices don't have an MPEG decoder built in,
 | 
			
		||||
	  so you need an external software decoder to watch TV.
 | 
			
		||||
 | 
			
		||||
	  To compile this driver as a module, say M here:
 | 
			
		||||
	  the module will be called firedtv.
 | 
			
		||||
 | 
			
		||||
if DVB_FIREDTV
 | 
			
		||||
 | 
			
		||||
config DVB_FIREDTV_IEEE1394
 | 
			
		||||
	def_bool IEEE1394
 | 
			
		||||
 | 
			
		||||
config DVB_FIREDTV_INPUT
 | 
			
		||||
	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
 | 
			
		||||
 | 
			
		||||
endif # DVB_FIREDTV
 | 
			
		||||
							
								
								
									
										8
									
								
								drivers/media/dvb/firewire/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								drivers/media/dvb/firewire/Makefile
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
 | 
			
		||||
 | 
			
		||||
firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
 | 
			
		||||
firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
 | 
			
		||||
firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
 | 
			
		||||
 | 
			
		||||
ccflags-y += -Idrivers/media/dvb/dvb-core
 | 
			
		||||
ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
 | 
			
		||||
							
								
								
									
										285
									
								
								drivers/media/dvb/firewire/firedtv-1394.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								drivers/media/dvb/firewire/firedtv-1394.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,285 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
 | 
			
		||||
 * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
 | 
			
		||||
 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
 | 
			
		||||
 *
 | 
			
		||||
 *	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/device.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include <dma.h>
 | 
			
		||||
#include <csr1212.h>
 | 
			
		||||
#include <highlevel.h>
 | 
			
		||||
#include <hosts.h>
 | 
			
		||||
#include <ieee1394.h>
 | 
			
		||||
#include <iso.h>
 | 
			
		||||
#include <nodemgr.h>
 | 
			
		||||
 | 
			
		||||
#include "firedtv.h"
 | 
			
		||||
 | 
			
		||||
static LIST_HEAD(node_list);
 | 
			
		||||
static DEFINE_SPINLOCK(node_list_lock);
 | 
			
		||||
 | 
			
		||||
#define FIREWIRE_HEADER_SIZE	4
 | 
			
		||||
#define CIP_HEADER_SIZE		8
 | 
			
		||||
 | 
			
		||||
static void rawiso_activity_cb(struct hpsb_iso *iso)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *f, *fdtv = NULL;
 | 
			
		||||
	unsigned int i, num, packet;
 | 
			
		||||
	unsigned char *buf;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int count;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&node_list_lock, flags);
 | 
			
		||||
	list_for_each_entry(f, &node_list, list)
 | 
			
		||||
		if (f->backend_data == iso) {
 | 
			
		||||
			fdtv = f;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	spin_unlock_irqrestore(&node_list_lock, flags);
 | 
			
		||||
 | 
			
		||||
	packet = iso->first_packet;
 | 
			
		||||
	num = hpsb_iso_n_ready(iso);
 | 
			
		||||
 | 
			
		||||
	if (!fdtv) {
 | 
			
		||||
		dev_err(fdtv->device, "received at unknown iso channel\n");
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
 | 
			
		||||
		buf = dma_region_i(&iso->data_buf, unsigned char,
 | 
			
		||||
			iso->infos[packet].offset + CIP_HEADER_SIZE);
 | 
			
		||||
		count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
 | 
			
		||||
			(188 + FIREWIRE_HEADER_SIZE);
 | 
			
		||||
 | 
			
		||||
		/* ignore empty packet */
 | 
			
		||||
		if (iso->infos[packet].len <= CIP_HEADER_SIZE)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		while (count--) {
 | 
			
		||||
			if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
 | 
			
		||||
				dvb_dmx_swfilter_packets(&fdtv->demux,
 | 
			
		||||
						&buf[FIREWIRE_HEADER_SIZE], 1);
 | 
			
		||||
			else
 | 
			
		||||
				dev_err(fdtv->device,
 | 
			
		||||
					"skipping invalid packet\n");
 | 
			
		||||
			buf += 188 + FIREWIRE_HEADER_SIZE;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	hpsb_iso_recv_release_packets(iso, num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct node_entry *node_of(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	return container_of(fdtv->device, struct unit_directory, device)->ne;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
 | 
			
		||||
{
 | 
			
		||||
	return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
 | 
			
		||||
			      (__force quadlet_t)arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	return hpsb_node_read(node_of(fdtv), addr, data, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
 | 
			
		||||
{
 | 
			
		||||
	return hpsb_node_write(node_of(fdtv), addr, data, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define FDTV_ISO_BUFFER_PACKETS 256
 | 
			
		||||
#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
 | 
			
		||||
 | 
			
		||||
static int start_iso(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	struct hpsb_iso *iso_handle;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
 | 
			
		||||
				FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
 | 
			
		||||
				fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
 | 
			
		||||
				-1, /* stat.config.irq_interval */
 | 
			
		||||
				rawiso_activity_cb);
 | 
			
		||||
	if (iso_handle == NULL) {
 | 
			
		||||
		dev_err(fdtv->device, "cannot initialize iso receive\n");
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
	fdtv->backend_data = iso_handle;
 | 
			
		||||
 | 
			
		||||
	ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
 | 
			
		||||
	if (ret != 0) {
 | 
			
		||||
		dev_err(fdtv->device, "cannot start iso receive\n");
 | 
			
		||||
		hpsb_iso_shutdown(iso_handle);
 | 
			
		||||
		fdtv->backend_data = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void stop_iso(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	struct hpsb_iso *iso_handle = fdtv->backend_data;
 | 
			
		||||
 | 
			
		||||
	if (iso_handle != NULL) {
 | 
			
		||||
		hpsb_iso_stop(iso_handle);
 | 
			
		||||
		hpsb_iso_shutdown(iso_handle);
 | 
			
		||||
	}
 | 
			
		||||
	fdtv->backend_data = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct firedtv_backend fdtv_1394_backend = {
 | 
			
		||||
	.lock		= node_lock,
 | 
			
		||||
	.read		= node_read,
 | 
			
		||||
	.write		= node_write,
 | 
			
		||||
	.start_iso	= start_iso,
 | 
			
		||||
	.stop_iso	= stop_iso,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
 | 
			
		||||
			int cts, u8 *data, size_t length)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *f, *fdtv = NULL;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int su;
 | 
			
		||||
 | 
			
		||||
	if (length == 0 || (data[0] & 0xf0) != 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	su = data[1] & 0x7;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irqsave(&node_list_lock, flags);
 | 
			
		||||
	list_for_each_entry(f, &node_list, list)
 | 
			
		||||
		if (node_of(f)->host == host &&
 | 
			
		||||
		    node_of(f)->nodeid == nodeid &&
 | 
			
		||||
		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
 | 
			
		||||
			fdtv = f;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	spin_unlock_irqrestore(&node_list_lock, flags);
 | 
			
		||||
 | 
			
		||||
	if (fdtv)
 | 
			
		||||
		avc_recv(fdtv, data, length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_probe(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct unit_directory *ud =
 | 
			
		||||
			container_of(dev, struct unit_directory, device);
 | 
			
		||||
	struct firedtv *fdtv;
 | 
			
		||||
	int kv_len, err;
 | 
			
		||||
	void *kv_str;
 | 
			
		||||
 | 
			
		||||
	kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
 | 
			
		||||
	kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
 | 
			
		||||
 | 
			
		||||
	fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
 | 
			
		||||
	if (!fdtv)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Work around a bug in udev's path_id script:  Use the fw-host's dev
 | 
			
		||||
	 * instead of the unit directory's dev as parent of the input device.
 | 
			
		||||
	 */
 | 
			
		||||
	err = fdtv_register_rc(fdtv, dev->parent->parent);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_free;
 | 
			
		||||
 | 
			
		||||
	spin_lock_irq(&node_list_lock);
 | 
			
		||||
	list_add_tail(&fdtv->list, &node_list);
 | 
			
		||||
	spin_unlock_irq(&node_list_lock);
 | 
			
		||||
 | 
			
		||||
	err = avc_identify_subunit(fdtv);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	err = fdtv_dvb_register(fdtv);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	avc_register_remote_control(fdtv);
 | 
			
		||||
	return 0;
 | 
			
		||||
fail:
 | 
			
		||||
	spin_lock_irq(&node_list_lock);
 | 
			
		||||
	list_del(&fdtv->list);
 | 
			
		||||
	spin_unlock_irq(&node_list_lock);
 | 
			
		||||
	fdtv_unregister_rc(fdtv);
 | 
			
		||||
fail_free:
 | 
			
		||||
	kfree(fdtv);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_remove(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = dev->driver_data;
 | 
			
		||||
 | 
			
		||||
	fdtv_dvb_unregister(fdtv);
 | 
			
		||||
 | 
			
		||||
	spin_lock_irq(&node_list_lock);
 | 
			
		||||
	list_del(&fdtv->list);
 | 
			
		||||
	spin_unlock_irq(&node_list_lock);
 | 
			
		||||
 | 
			
		||||
	cancel_work_sync(&fdtv->remote_ctrl_work);
 | 
			
		||||
	fdtv_unregister_rc(fdtv);
 | 
			
		||||
 | 
			
		||||
	kfree(fdtv);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int node_update(struct unit_directory *ud)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = ud->device.driver_data;
 | 
			
		||||
 | 
			
		||||
	if (fdtv->isochannel >= 0)
 | 
			
		||||
		cmp_establish_pp_connection(fdtv, fdtv->subunit,
 | 
			
		||||
					    fdtv->isochannel);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct hpsb_protocol_driver fdtv_driver = {
 | 
			
		||||
	.name		= "firedtv",
 | 
			
		||||
	.update		= node_update,
 | 
			
		||||
	.driver         = {
 | 
			
		||||
		.probe  = node_probe,
 | 
			
		||||
		.remove = node_remove,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct hpsb_highlevel fdtv_highlevel = {
 | 
			
		||||
	.name		= "firedtv",
 | 
			
		||||
	.fcp_request	= fcp_request,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
 | 
			
		||||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	hpsb_register_highlevel(&fdtv_highlevel);
 | 
			
		||||
	fdtv_driver.id_table = id_table;
 | 
			
		||||
	ret = hpsb_register_protocol(&fdtv_driver);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		printk(KERN_ERR "firedtv: failed to register protocol\n");
 | 
			
		||||
		hpsb_unregister_highlevel(&fdtv_highlevel);
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __exit fdtv_1394_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	hpsb_unregister_protocol(&fdtv_driver);
 | 
			
		||||
	hpsb_unregister_highlevel(&fdtv_highlevel);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1315
									
								
								drivers/media/dvb/firewire/firedtv-avc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1315
									
								
								drivers/media/dvb/firewire/firedtv-avc.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										260
									
								
								drivers/media/dvb/firewire/firedtv-ci.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								drivers/media/dvb/firewire/firedtv-ci.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,260 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
 | 
			
		||||
 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
 | 
			
		||||
 *
 | 
			
		||||
 *	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/device.h>
 | 
			
		||||
#include <linux/dvb/ca.h>
 | 
			
		||||
#include <linux/fs.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
 | 
			
		||||
#include <dvbdev.h>
 | 
			
		||||
 | 
			
		||||
#include "firedtv.h"
 | 
			
		||||
 | 
			
		||||
#define EN50221_TAG_APP_INFO_ENQUIRY	0x9f8020
 | 
			
		||||
#define EN50221_TAG_CA_INFO_ENQUIRY	0x9f8030
 | 
			
		||||
#define EN50221_TAG_CA_PMT		0x9f8032
 | 
			
		||||
#define EN50221_TAG_ENTER_MENU		0x9f8022
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
 | 
			
		||||
{
 | 
			
		||||
	return stat->ca_initialization_status	== 1 &&
 | 
			
		||||
	       stat->ca_error_flag		== 0 &&
 | 
			
		||||
	       stat->ca_dvb_flag		== 1 &&
 | 
			
		||||
	       stat->ca_module_present_status	== 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
 | 
			
		||||
{
 | 
			
		||||
	int flags = 0;
 | 
			
		||||
 | 
			
		||||
	if (stat->ca_module_present_status == 1)
 | 
			
		||||
		flags |= CA_CI_MODULE_PRESENT;
 | 
			
		||||
	if (stat->ca_initialization_status == 1 &&
 | 
			
		||||
	    stat->ca_error_flag            == 0 &&
 | 
			
		||||
	    stat->ca_dvb_flag              == 1)
 | 
			
		||||
		flags |= CA_CI_MODULE_READY;
 | 
			
		||||
	return flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_reset(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	return avc_ca_reset(fdtv) ? -EFAULT : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_get_caps(void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_caps *cap = arg;
 | 
			
		||||
 | 
			
		||||
	cap->slot_num = 1;
 | 
			
		||||
	cap->slot_type = CA_CI;
 | 
			
		||||
	cap->descr_num = 1;
 | 
			
		||||
	cap->descr_type = CA_ECD;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
	struct ca_slot_info *slot = arg;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	if (slot->num != 0)
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	slot->type = CA_CI;
 | 
			
		||||
	slot->flags = fdtv_get_ca_flags(&stat);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_msg *reply = arg;
 | 
			
		||||
 | 
			
		||||
	return avc_ca_app_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_msg *reply = arg;
 | 
			
		||||
 | 
			
		||||
	return avc_ca_info(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_msg *reply = arg;
 | 
			
		||||
 | 
			
		||||
	return avc_ca_get_mmi(fdtv, reply->msg, &reply->length) ? -EFAULT : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	switch (fdtv->ca_last_command) {
 | 
			
		||||
	case EN50221_TAG_APP_INFO_ENQUIRY:
 | 
			
		||||
		err = fdtv_ca_app_info(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	case EN50221_TAG_CA_INFO_ENQUIRY:
 | 
			
		||||
		err = fdtv_ca_info(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
			err = -EFAULT;
 | 
			
		||||
		else if (stat.ca_mmi == 1)
 | 
			
		||||
			err = fdtv_ca_get_mmi(fdtv, arg);
 | 
			
		||||
		else {
 | 
			
		||||
			dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
 | 
			
		||||
				 fdtv->ca_last_command);
 | 
			
		||||
			err = -EFAULT;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	fdtv->ca_last_command = 0;
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_msg *msg = arg;
 | 
			
		||||
	int data_pos;
 | 
			
		||||
	int data_length;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	data_pos = 4;
 | 
			
		||||
	if (msg->msg[3] & 0x80) {
 | 
			
		||||
		data_length = 0;
 | 
			
		||||
		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
 | 
			
		||||
			data_length = (data_length << 8) + msg->msg[data_pos++];
 | 
			
		||||
	} else {
 | 
			
		||||
		data_length = msg->msg[3];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length) ? -EFAULT : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct ca_msg *msg = arg;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	/* Do we need a semaphore for this? */
 | 
			
		||||
	fdtv->ca_last_command =
 | 
			
		||||
		(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
 | 
			
		||||
	switch (fdtv->ca_last_command) {
 | 
			
		||||
	case EN50221_TAG_CA_PMT:
 | 
			
		||||
		err = fdtv_ca_pmt(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	case EN50221_TAG_APP_INFO_ENQUIRY:
 | 
			
		||||
		/* handled in ca_get_msg */
 | 
			
		||||
		err = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case EN50221_TAG_CA_INFO_ENQUIRY:
 | 
			
		||||
		/* handled in ca_get_msg */
 | 
			
		||||
		err = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case EN50221_TAG_ENTER_MENU:
 | 
			
		||||
		err = avc_ca_enter_menu(fdtv);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
 | 
			
		||||
			fdtv->ca_last_command);
 | 
			
		||||
		err = -EFAULT;
 | 
			
		||||
	}
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_ca_ioctl(struct inode *inode, struct file *file,
 | 
			
		||||
			    unsigned int cmd, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_device *dvbdev = file->private_data;
 | 
			
		||||
	struct firedtv *fdtv = dvbdev->priv;
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
	case CA_RESET:
 | 
			
		||||
		err = fdtv_ca_reset(fdtv);
 | 
			
		||||
		break;
 | 
			
		||||
	case CA_GET_CAP:
 | 
			
		||||
		err = fdtv_ca_get_caps(arg);
 | 
			
		||||
		break;
 | 
			
		||||
	case CA_GET_SLOT_INFO:
 | 
			
		||||
		err = fdtv_ca_get_slot_info(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	case CA_GET_MSG:
 | 
			
		||||
		err = fdtv_ca_get_msg(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	case CA_SEND_MSG:
 | 
			
		||||
		err = fdtv_ca_send_msg(fdtv, arg);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
 | 
			
		||||
		err = -EOPNOTSUPP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* FIXME Is this necessary? */
 | 
			
		||||
	avc_tuner_status(fdtv, &stat);
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
 | 
			
		||||
{
 | 
			
		||||
	return POLLIN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct file_operations fdtv_ca_fops = {
 | 
			
		||||
	.owner		= THIS_MODULE,
 | 
			
		||||
	.ioctl		= dvb_generic_ioctl,
 | 
			
		||||
	.open		= dvb_generic_open,
 | 
			
		||||
	.release	= dvb_generic_release,
 | 
			
		||||
	.poll		= fdtv_ca_io_poll,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct dvb_device fdtv_ca = {
 | 
			
		||||
	.users		= 1,
 | 
			
		||||
	.readers	= 1,
 | 
			
		||||
	.writers	= 1,
 | 
			
		||||
	.fops		= &fdtv_ca_fops,
 | 
			
		||||
	.kernel_ioctl	= fdtv_ca_ioctl,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int fdtv_ca_register(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (!fdtv_ca_ready(&stat))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
 | 
			
		||||
				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
 | 
			
		||||
 | 
			
		||||
	if (stat.ca_application_info == 0)
 | 
			
		||||
		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
 | 
			
		||||
	if (stat.ca_date_time_request == 1)
 | 
			
		||||
		avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fdtv_ca_release(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	if (fdtv->cadev)
 | 
			
		||||
		dvb_unregister_device(fdtv->cadev);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										364
									
								
								drivers/media/dvb/firewire/firedtv-dvb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								drivers/media/dvb/firewire/firedtv-dvb.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,364 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
 | 
			
		||||
 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
 | 
			
		||||
 *
 | 
			
		||||
 *	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/bitops.h>
 | 
			
		||||
#include <linux/device.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/mod_devicetable.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/workqueue.h>
 | 
			
		||||
 | 
			
		||||
#include <dmxdev.h>
 | 
			
		||||
#include <dvb_demux.h>
 | 
			
		||||
#include <dvbdev.h>
 | 
			
		||||
#include <dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#include "firedtv.h"
 | 
			
		||||
 | 
			
		||||
static int alloc_channel(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 16; i++)
 | 
			
		||||
		if (!__test_and_set_bit(i, &fdtv->channel_active))
 | 
			
		||||
			break;
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
 | 
			
		||||
{
 | 
			
		||||
	int i, n;
 | 
			
		||||
 | 
			
		||||
	for (i = 0, n = 0; i < 16; i++)
 | 
			
		||||
		if (test_bit(i, &fdtv->channel_active))
 | 
			
		||||
			pid[n++] = fdtv->channel_pid[i];
 | 
			
		||||
	*pidc = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void dealloc_channel(struct firedtv *fdtv, int i)
 | 
			
		||||
{
 | 
			
		||||
	__clear_bit(i, &fdtv->channel_active);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = dvbdmxfeed->demux->priv;
 | 
			
		||||
	int pidc, c, ret;
 | 
			
		||||
	u16 pids[16];
 | 
			
		||||
 | 
			
		||||
	switch (dvbdmxfeed->type) {
 | 
			
		||||
	case DMX_TYPE_TS:
 | 
			
		||||
	case DMX_TYPE_SEC:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
 | 
			
		||||
			dvbdmxfeed->type);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mutex_lock_interruptible(&fdtv->demux_mutex))
 | 
			
		||||
		return -EINTR;
 | 
			
		||||
 | 
			
		||||
	if (dvbdmxfeed->type == DMX_TYPE_TS) {
 | 
			
		||||
		switch (dvbdmxfeed->pes_type) {
 | 
			
		||||
		case DMX_TS_PES_VIDEO:
 | 
			
		||||
		case DMX_TS_PES_AUDIO:
 | 
			
		||||
		case DMX_TS_PES_TELETEXT:
 | 
			
		||||
		case DMX_TS_PES_PCR:
 | 
			
		||||
		case DMX_TS_PES_OTHER:
 | 
			
		||||
			c = alloc_channel(fdtv);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			dev_err(fdtv->device,
 | 
			
		||||
				"can't start dmx feed: invalid pes type %u\n",
 | 
			
		||||
				dvbdmxfeed->pes_type);
 | 
			
		||||
			ret = -EINVAL;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		c = alloc_channel(fdtv);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (c > 15) {
 | 
			
		||||
		dev_err(fdtv->device, "can't start dmx feed: busy\n");
 | 
			
		||||
		ret = -EBUSY;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
 | 
			
		||||
	fdtv->channel_pid[c] = dvbdmxfeed->pid;
 | 
			
		||||
	collect_channels(fdtv, &pidc, pids);
 | 
			
		||||
 | 
			
		||||
	if (dvbdmxfeed->pid == 8192) {
 | 
			
		||||
		ret = avc_tuner_get_ts(fdtv);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			dealloc_channel(fdtv, c);
 | 
			
		||||
			dev_err(fdtv->device, "can't get TS\n");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = avc_tuner_set_pids(fdtv, pidc, pids);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			dealloc_channel(fdtv, c);
 | 
			
		||||
			dev_err(fdtv->device, "can't set PIDs\n");
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	mutex_unlock(&fdtv->demux_mutex);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_demux *demux = dvbdmxfeed->demux;
 | 
			
		||||
	struct firedtv *fdtv = demux->priv;
 | 
			
		||||
	int pidc, c, ret;
 | 
			
		||||
	u16 pids[16];
 | 
			
		||||
 | 
			
		||||
	if (dvbdmxfeed->type == DMX_TYPE_TS &&
 | 
			
		||||
	    !((dvbdmxfeed->ts_type & TS_PACKET) &&
 | 
			
		||||
	      (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
 | 
			
		||||
 | 
			
		||||
		if (dvbdmxfeed->ts_type & TS_DECODER) {
 | 
			
		||||
			if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
 | 
			
		||||
			    !demux->pesfilter[dvbdmxfeed->pes_type])
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
 | 
			
		||||
			demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
 | 
			
		||||
			demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!(dvbdmxfeed->ts_type & TS_DECODER &&
 | 
			
		||||
		      dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mutex_lock_interruptible(&fdtv->demux_mutex))
 | 
			
		||||
		return -EINTR;
 | 
			
		||||
 | 
			
		||||
	c = (unsigned long)dvbdmxfeed->priv;
 | 
			
		||||
	dealloc_channel(fdtv, c);
 | 
			
		||||
	collect_channels(fdtv, &pidc, pids);
 | 
			
		||||
 | 
			
		||||
	ret = avc_tuner_set_pids(fdtv, pidc, pids);
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&fdtv->demux_mutex);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 | 
			
		||||
 | 
			
		||||
int fdtv_dvb_register(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
 | 
			
		||||
				   THIS_MODULE, fdtv->device, adapter_nr);
 | 
			
		||||
	if (err < 0)
 | 
			
		||||
		goto fail_log;
 | 
			
		||||
 | 
			
		||||
	/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
 | 
			
		||||
	fdtv->demux.dmx.capabilities = 0;
 | 
			
		||||
 | 
			
		||||
	fdtv->demux.priv	= fdtv;
 | 
			
		||||
	fdtv->demux.filternum	= 16;
 | 
			
		||||
	fdtv->demux.feednum	= 16;
 | 
			
		||||
	fdtv->demux.start_feed	= fdtv_start_feed;
 | 
			
		||||
	fdtv->demux.stop_feed	= fdtv_stop_feed;
 | 
			
		||||
	fdtv->demux.write_to_decoder = NULL;
 | 
			
		||||
 | 
			
		||||
	err = dvb_dmx_init(&fdtv->demux);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_unreg_adapter;
 | 
			
		||||
 | 
			
		||||
	fdtv->dmxdev.filternum    = 16;
 | 
			
		||||
	fdtv->dmxdev.demux        = &fdtv->demux.dmx;
 | 
			
		||||
	fdtv->dmxdev.capabilities = 0;
 | 
			
		||||
 | 
			
		||||
	err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_dmx_release;
 | 
			
		||||
 | 
			
		||||
	fdtv->frontend.source = DMX_FRONTEND_0;
 | 
			
		||||
 | 
			
		||||
	err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_dmxdev_release;
 | 
			
		||||
 | 
			
		||||
	err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
 | 
			
		||||
					       &fdtv->frontend);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_rem_frontend;
 | 
			
		||||
 | 
			
		||||
	dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
 | 
			
		||||
 | 
			
		||||
	fdtv_frontend_init(fdtv);
 | 
			
		||||
	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_net_release;
 | 
			
		||||
 | 
			
		||||
	err = fdtv_ca_register(fdtv);
 | 
			
		||||
	if (err)
 | 
			
		||||
		dev_info(fdtv->device,
 | 
			
		||||
			 "Conditional Access Module not enabled\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
fail_net_release:
 | 
			
		||||
	dvb_net_release(&fdtv->dvbnet);
 | 
			
		||||
	fdtv->demux.dmx.close(&fdtv->demux.dmx);
 | 
			
		||||
fail_rem_frontend:
 | 
			
		||||
	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 | 
			
		||||
fail_dmxdev_release:
 | 
			
		||||
	dvb_dmxdev_release(&fdtv->dmxdev);
 | 
			
		||||
fail_dmx_release:
 | 
			
		||||
	dvb_dmx_release(&fdtv->demux);
 | 
			
		||||
fail_unreg_adapter:
 | 
			
		||||
	dvb_unregister_adapter(&fdtv->adapter);
 | 
			
		||||
fail_log:
 | 
			
		||||
	dev_err(fdtv->device, "DVB initialization failed\n");
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fdtv_dvb_unregister(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	fdtv_ca_release(fdtv);
 | 
			
		||||
	dvb_unregister_frontend(&fdtv->fe);
 | 
			
		||||
	dvb_net_release(&fdtv->dvbnet);
 | 
			
		||||
	fdtv->demux.dmx.close(&fdtv->demux.dmx);
 | 
			
		||||
	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
 | 
			
		||||
	dvb_dmxdev_release(&fdtv->dmxdev);
 | 
			
		||||
	dvb_dmx_release(&fdtv->demux);
 | 
			
		||||
	dvb_unregister_adapter(&fdtv->adapter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *fdtv_model_names[] = {
 | 
			
		||||
	[FIREDTV_UNKNOWN] = "unknown type",
 | 
			
		||||
	[FIREDTV_DVB_S]   = "FireDTV S/CI",
 | 
			
		||||
	[FIREDTV_DVB_C]   = "FireDTV C/CI",
 | 
			
		||||
	[FIREDTV_DVB_T]   = "FireDTV T/CI",
 | 
			
		||||
	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct firedtv *fdtv_alloc(struct device *dev,
 | 
			
		||||
			   const struct firedtv_backend *backend,
 | 
			
		||||
			   const char *name, size_t name_len)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
 | 
			
		||||
	if (!fdtv)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	dev->driver_data	= fdtv;
 | 
			
		||||
	fdtv->device		= dev;
 | 
			
		||||
	fdtv->isochannel	= -1;
 | 
			
		||||
	fdtv->voltage		= 0xff;
 | 
			
		||||
	fdtv->tone		= 0xff;
 | 
			
		||||
	fdtv->backend		= backend;
 | 
			
		||||
 | 
			
		||||
	mutex_init(&fdtv->avc_mutex);
 | 
			
		||||
	init_waitqueue_head(&fdtv->avc_wait);
 | 
			
		||||
	fdtv->avc_reply_received = true;
 | 
			
		||||
	mutex_init(&fdtv->demux_mutex);
 | 
			
		||||
	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
 | 
			
		||||
 | 
			
		||||
	for (i = ARRAY_SIZE(fdtv_model_names); --i; )
 | 
			
		||||
		if (strlen(fdtv_model_names[i]) <= name_len &&
 | 
			
		||||
		    strncmp(name, fdtv_model_names[i], name_len) == 0)
 | 
			
		||||
			break;
 | 
			
		||||
	fdtv->type = i;
 | 
			
		||||
 | 
			
		||||
	return fdtv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
 | 
			
		||||
		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
 | 
			
		||||
 | 
			
		||||
#define DIGITAL_EVERYWHERE_OUI	0x001287
 | 
			
		||||
#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
 | 
			
		||||
#define AVC_SW_VERSION_ENTRY	0x010001
 | 
			
		||||
 | 
			
		||||
static struct ieee1394_device_id fdtv_id_table[] = {
 | 
			
		||||
	{
 | 
			
		||||
		/* FloppyDTV S/CI and FloppyDTV S2 */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000024,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {
 | 
			
		||||
		/* FloppyDTV T/CI */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000025,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {
 | 
			
		||||
		/* FloppyDTV C/CI */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000026,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {
 | 
			
		||||
		/* FireDTV S/CI and FloppyDTV S2 */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000034,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {
 | 
			
		||||
		/* FireDTV T/CI */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000035,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {
 | 
			
		||||
		/* FireDTV C/CI */
 | 
			
		||||
		.match_flags	= MATCH_FLAGS,
 | 
			
		||||
		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
 | 
			
		||||
		.model_id	= 0x000036,
 | 
			
		||||
		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
 | 
			
		||||
		.version	= AVC_SW_VERSION_ENTRY,
 | 
			
		||||
	}, {}
 | 
			
		||||
};
 | 
			
		||||
MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
 | 
			
		||||
 | 
			
		||||
static int __init fdtv_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return fdtv_1394_init(fdtv_id_table);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __exit fdtv_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	fdtv_1394_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(fdtv_init);
 | 
			
		||||
module_exit(fdtv_exit);
 | 
			
		||||
 | 
			
		||||
MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
 | 
			
		||||
MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
 | 
			
		||||
MODULE_DESCRIPTION("FireDTV DVB Driver");
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
MODULE_SUPPORTED_DEVICE("FireDTV DVB");
 | 
			
		||||
							
								
								
									
										247
									
								
								drivers/media/dvb/firewire/firedtv-fe.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								drivers/media/dvb/firewire/firedtv-fe.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,247 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
 | 
			
		||||
 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
 | 
			
		||||
 *
 | 
			
		||||
 *	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/device.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include <dvb_frontend.h>
 | 
			
		||||
 | 
			
		||||
#include "firedtv.h"
 | 
			
		||||
 | 
			
		||||
static int fdtv_dvb_init(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	/* FIXME - allocate free channel at IRM */
 | 
			
		||||
	fdtv->isochannel = fdtv->adapter.num;
 | 
			
		||||
 | 
			
		||||
	err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
 | 
			
		||||
					  fdtv->isochannel);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		dev_err(fdtv->device,
 | 
			
		||||
			"could not establish point to point connection\n");
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fdtv->backend->start_iso(fdtv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_sleep(struct dvb_frontend *fe)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
 | 
			
		||||
	fdtv->backend->stop_iso(fdtv);
 | 
			
		||||
	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
 | 
			
		||||
	fdtv->isochannel = -1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define LNBCONTROL_DONTCARE 0xff
 | 
			
		||||
 | 
			
		||||
static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
 | 
			
		||||
				       struct dvb_diseqc_master_cmd *cmd)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
 | 
			
		||||
	return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
 | 
			
		||||
			       LNBCONTROL_DONTCARE, 1, cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
 | 
			
		||||
				  fe_sec_mini_cmd_t minicmd)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
 | 
			
		||||
	fdtv->tone = tone;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_set_voltage(struct dvb_frontend *fe,
 | 
			
		||||
			    fe_sec_voltage_t voltage)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
 | 
			
		||||
	fdtv->voltage = voltage;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (stat.no_rf)
 | 
			
		||||
		*status = 0;
 | 
			
		||||
	else
 | 
			
		||||
		*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
 | 
			
		||||
			  FE_HAS_CARRIER | FE_HAS_LOCK;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	*ber = stat.ber;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	*strength = stat.signal_strength << 8;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
	struct firedtv_tuner_status stat;
 | 
			
		||||
 | 
			
		||||
	if (avc_tuner_status(fdtv, &stat))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* C/N[dB] = -10 * log10(snr / 65535) */
 | 
			
		||||
	*snr = stat.carrier_noise_ratio * 257;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
 | 
			
		||||
{
 | 
			
		||||
	return -EOPNOTSUPP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ACCEPTED 0x9
 | 
			
		||||
 | 
			
		||||
static int fdtv_set_frontend(struct dvb_frontend *fe,
 | 
			
		||||
			     struct dvb_frontend_parameters *params)
 | 
			
		||||
{
 | 
			
		||||
	struct firedtv *fdtv = fe->sec_priv;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */
 | 
			
		||||
	if (avc_tuner_dsd(fdtv, params) != ACCEPTED)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	else
 | 
			
		||||
		return 0; /* not sure of this... */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdtv_get_frontend(struct dvb_frontend *fe,
 | 
			
		||||
			     struct dvb_frontend_parameters *params)
 | 
			
		||||
{
 | 
			
		||||
	return -EOPNOTSUPP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fdtv_frontend_init(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
 | 
			
		||||
	struct dvb_frontend_info *fi = &ops->info;
 | 
			
		||||
 | 
			
		||||
	ops->init			= fdtv_dvb_init;
 | 
			
		||||
	ops->sleep			= fdtv_sleep;
 | 
			
		||||
 | 
			
		||||
	ops->set_frontend		= fdtv_set_frontend;
 | 
			
		||||
	ops->get_frontend		= fdtv_get_frontend;
 | 
			
		||||
 | 
			
		||||
	ops->read_status		= fdtv_read_status;
 | 
			
		||||
	ops->read_ber			= fdtv_read_ber;
 | 
			
		||||
	ops->read_signal_strength	= fdtv_read_signal_strength;
 | 
			
		||||
	ops->read_snr			= fdtv_read_snr;
 | 
			
		||||
	ops->read_ucblocks		= fdtv_read_uncorrected_blocks;
 | 
			
		||||
 | 
			
		||||
	ops->diseqc_send_master_cmd 	= fdtv_diseqc_send_master_cmd;
 | 
			
		||||
	ops->diseqc_send_burst		= fdtv_diseqc_send_burst;
 | 
			
		||||
	ops->set_tone			= fdtv_set_tone;
 | 
			
		||||
	ops->set_voltage		= fdtv_set_voltage;
 | 
			
		||||
 | 
			
		||||
	switch (fdtv->type) {
 | 
			
		||||
	case FIREDTV_DVB_S:
 | 
			
		||||
	case FIREDTV_DVB_S2:
 | 
			
		||||
		fi->type		= FE_QPSK;
 | 
			
		||||
 | 
			
		||||
		fi->frequency_min	= 950000;
 | 
			
		||||
		fi->frequency_max	= 2150000;
 | 
			
		||||
		fi->frequency_stepsize	= 125;
 | 
			
		||||
		fi->symbol_rate_min	= 1000000;
 | 
			
		||||
		fi->symbol_rate_max	= 40000000;
 | 
			
		||||
 | 
			
		||||
		fi->caps 		= FE_CAN_INVERSION_AUTO	|
 | 
			
		||||
					  FE_CAN_FEC_1_2	|
 | 
			
		||||
					  FE_CAN_FEC_2_3	|
 | 
			
		||||
					  FE_CAN_FEC_3_4	|
 | 
			
		||||
					  FE_CAN_FEC_5_6	|
 | 
			
		||||
					  FE_CAN_FEC_7_8	|
 | 
			
		||||
					  FE_CAN_FEC_AUTO	|
 | 
			
		||||
					  FE_CAN_QPSK;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case FIREDTV_DVB_C:
 | 
			
		||||
		fi->type		= FE_QAM;
 | 
			
		||||
 | 
			
		||||
		fi->frequency_min	= 47000000;
 | 
			
		||||
		fi->frequency_max	= 866000000;
 | 
			
		||||
		fi->frequency_stepsize	= 62500;
 | 
			
		||||
		fi->symbol_rate_min	= 870000;
 | 
			
		||||
		fi->symbol_rate_max	= 6900000;
 | 
			
		||||
 | 
			
		||||
		fi->caps 		= FE_CAN_INVERSION_AUTO |
 | 
			
		||||
					  FE_CAN_QAM_16		|
 | 
			
		||||
					  FE_CAN_QAM_32		|
 | 
			
		||||
					  FE_CAN_QAM_64		|
 | 
			
		||||
					  FE_CAN_QAM_128	|
 | 
			
		||||
					  FE_CAN_QAM_256	|
 | 
			
		||||
					  FE_CAN_QAM_AUTO;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case FIREDTV_DVB_T:
 | 
			
		||||
		fi->type		= FE_OFDM;
 | 
			
		||||
 | 
			
		||||
		fi->frequency_min	= 49000000;
 | 
			
		||||
		fi->frequency_max	= 861000000;
 | 
			
		||||
		fi->frequency_stepsize	= 62500;
 | 
			
		||||
 | 
			
		||||
		fi->caps 		= FE_CAN_INVERSION_AUTO		|
 | 
			
		||||
					  FE_CAN_FEC_2_3		|
 | 
			
		||||
					  FE_CAN_TRANSMISSION_MODE_AUTO |
 | 
			
		||||
					  FE_CAN_GUARD_INTERVAL_AUTO	|
 | 
			
		||||
					  FE_CAN_HIERARCHY_AUTO;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		dev_err(fdtv->device, "no frontend for model type %d\n",
 | 
			
		||||
			fdtv->type);
 | 
			
		||||
	}
 | 
			
		||||
	strcpy(fi->name, fdtv_model_names[fdtv->type]);
 | 
			
		||||
 | 
			
		||||
	fdtv->fe.dvb = &fdtv->adapter;
 | 
			
		||||
	fdtv->fe.sec_priv = fdtv;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										190
									
								
								drivers/media/dvb/firewire/firedtv-rc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								drivers/media/dvb/firewire/firedtv-rc.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,190 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/bitops.h>
 | 
			
		||||
#include <linux/input.h>
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include "firedtv.h"
 | 
			
		||||
 | 
			
		||||
/* fixed table with older keycodes, geared towards MythTV */
 | 
			
		||||
const static u16 oldtable[] = {
 | 
			
		||||
 | 
			
		||||
	/* code from device: 0x4501...0x451f */
 | 
			
		||||
 | 
			
		||||
	KEY_ESC,
 | 
			
		||||
	KEY_F9,
 | 
			
		||||
	KEY_1,
 | 
			
		||||
	KEY_2,
 | 
			
		||||
	KEY_3,
 | 
			
		||||
	KEY_4,
 | 
			
		||||
	KEY_5,
 | 
			
		||||
	KEY_6,
 | 
			
		||||
	KEY_7,
 | 
			
		||||
	KEY_8,
 | 
			
		||||
	KEY_9,
 | 
			
		||||
	KEY_I,
 | 
			
		||||
	KEY_0,
 | 
			
		||||
	KEY_ENTER,
 | 
			
		||||
	KEY_RED,
 | 
			
		||||
	KEY_UP,
 | 
			
		||||
	KEY_GREEN,
 | 
			
		||||
	KEY_F10,
 | 
			
		||||
	KEY_SPACE,
 | 
			
		||||
	KEY_F11,
 | 
			
		||||
	KEY_YELLOW,
 | 
			
		||||
	KEY_DOWN,
 | 
			
		||||
	KEY_BLUE,
 | 
			
		||||
	KEY_Z,
 | 
			
		||||
	KEY_P,
 | 
			
		||||
	KEY_PAGEDOWN,
 | 
			
		||||
	KEY_LEFT,
 | 
			
		||||
	KEY_W,
 | 
			
		||||
	KEY_RIGHT,
 | 
			
		||||
	KEY_P,
 | 
			
		||||
	KEY_M,
 | 
			
		||||
 | 
			
		||||
	/* code from device: 0x4540...0x4542 */
 | 
			
		||||
 | 
			
		||||
	KEY_R,
 | 
			
		||||
	KEY_V,
 | 
			
		||||
	KEY_C,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* user-modifiable table for a remote as sold in 2008 */
 | 
			
		||||
const static u16 keytable[] = {
 | 
			
		||||
 | 
			
		||||
	/* code from device: 0x0300...0x031f */
 | 
			
		||||
 | 
			
		||||
	[0x00] = KEY_POWER,
 | 
			
		||||
	[0x01] = KEY_SLEEP,
 | 
			
		||||
	[0x02] = KEY_STOP,
 | 
			
		||||
	[0x03] = KEY_OK,
 | 
			
		||||
	[0x04] = KEY_RIGHT,
 | 
			
		||||
	[0x05] = KEY_1,
 | 
			
		||||
	[0x06] = KEY_2,
 | 
			
		||||
	[0x07] = KEY_3,
 | 
			
		||||
	[0x08] = KEY_LEFT,
 | 
			
		||||
	[0x09] = KEY_4,
 | 
			
		||||
	[0x0a] = KEY_5,
 | 
			
		||||
	[0x0b] = KEY_6,
 | 
			
		||||
	[0x0c] = KEY_UP,
 | 
			
		||||
	[0x0d] = KEY_7,
 | 
			
		||||
	[0x0e] = KEY_8,
 | 
			
		||||
	[0x0f] = KEY_9,
 | 
			
		||||
	[0x10] = KEY_DOWN,
 | 
			
		||||
	[0x11] = KEY_TITLE,	/* "OSD" - fixme */
 | 
			
		||||
	[0x12] = KEY_0,
 | 
			
		||||
	[0x13] = KEY_F20,	/* "16:9" - fixme */
 | 
			
		||||
	[0x14] = KEY_SCREEN,	/* "FULL" - fixme */
 | 
			
		||||
	[0x15] = KEY_MUTE,
 | 
			
		||||
	[0x16] = KEY_SUBTITLE,
 | 
			
		||||
	[0x17] = KEY_RECORD,
 | 
			
		||||
	[0x18] = KEY_TEXT,
 | 
			
		||||
	[0x19] = KEY_AUDIO,
 | 
			
		||||
	[0x1a] = KEY_RED,
 | 
			
		||||
	[0x1b] = KEY_PREVIOUS,
 | 
			
		||||
	[0x1c] = KEY_REWIND,
 | 
			
		||||
	[0x1d] = KEY_PLAYPAUSE,
 | 
			
		||||
	[0x1e] = KEY_NEXT,
 | 
			
		||||
	[0x1f] = KEY_VOLUMEUP,
 | 
			
		||||
 | 
			
		||||
	/* code from device: 0x0340...0x0354 */
 | 
			
		||||
 | 
			
		||||
	[0x20] = KEY_CHANNELUP,
 | 
			
		||||
	[0x21] = KEY_F21,	/* "4:3" - fixme */
 | 
			
		||||
	[0x22] = KEY_TV,
 | 
			
		||||
	[0x23] = KEY_DVD,
 | 
			
		||||
	[0x24] = KEY_VCR,
 | 
			
		||||
	[0x25] = KEY_AUX,
 | 
			
		||||
	[0x26] = KEY_GREEN,
 | 
			
		||||
	[0x27] = KEY_YELLOW,
 | 
			
		||||
	[0x28] = KEY_BLUE,
 | 
			
		||||
	[0x29] = KEY_CHANNEL,	/* "CH.LIST" */
 | 
			
		||||
	[0x2a] = KEY_VENDOR,	/* "CI" - fixme */
 | 
			
		||||
	[0x2b] = KEY_VOLUMEDOWN,
 | 
			
		||||
	[0x2c] = KEY_CHANNELDOWN,
 | 
			
		||||
	[0x2d] = KEY_LAST,
 | 
			
		||||
	[0x2e] = KEY_INFO,
 | 
			
		||||
	[0x2f] = KEY_FORWARD,
 | 
			
		||||
	[0x30] = KEY_LIST,
 | 
			
		||||
	[0x31] = KEY_FAVORITES,
 | 
			
		||||
	[0x32] = KEY_MENU,
 | 
			
		||||
	[0x33] = KEY_EPG,
 | 
			
		||||
	[0x34] = KEY_EXIT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct input_dev *idev;
 | 
			
		||||
	int i, err;
 | 
			
		||||
 | 
			
		||||
	idev = input_allocate_device();
 | 
			
		||||
	if (!idev)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	fdtv->remote_ctrl_dev = idev;
 | 
			
		||||
	idev->name = "FireDTV remote control";
 | 
			
		||||
	idev->dev.parent = dev;
 | 
			
		||||
	idev->evbit[0] = BIT_MASK(EV_KEY);
 | 
			
		||||
	idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
 | 
			
		||||
	if (!idev->keycode) {
 | 
			
		||||
		err = -ENOMEM;
 | 
			
		||||
		goto fail;
 | 
			
		||||
	}
 | 
			
		||||
	idev->keycodesize = sizeof(keytable[0]);
 | 
			
		||||
	idev->keycodemax = ARRAY_SIZE(keytable);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < ARRAY_SIZE(keytable); i++)
 | 
			
		||||
		set_bit(keytable[i], idev->keybit);
 | 
			
		||||
 | 
			
		||||
	err = input_register_device(idev);
 | 
			
		||||
	if (err)
 | 
			
		||||
		goto fail_free_keymap;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
fail_free_keymap:
 | 
			
		||||
	kfree(idev->keycode);
 | 
			
		||||
fail:
 | 
			
		||||
	input_free_device(idev);
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fdtv_unregister_rc(struct firedtv *fdtv)
 | 
			
		||||
{
 | 
			
		||||
	kfree(fdtv->remote_ctrl_dev->keycode);
 | 
			
		||||
	input_unregister_device(fdtv->remote_ctrl_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
 | 
			
		||||
{
 | 
			
		||||
	u16 *keycode = fdtv->remote_ctrl_dev->keycode;
 | 
			
		||||
 | 
			
		||||
	if (code >= 0x0300 && code <= 0x031f)
 | 
			
		||||
		code = keycode[code - 0x0300];
 | 
			
		||||
	else if (code >= 0x0340 && code <= 0x0354)
 | 
			
		||||
		code = keycode[code - 0x0320];
 | 
			
		||||
	else if (code >= 0x4501 && code <= 0x451f)
 | 
			
		||||
		code = oldtable[code - 0x4501];
 | 
			
		||||
	else if (code >= 0x4540 && code <= 0x4542)
 | 
			
		||||
		code = oldtable[code - 0x4521];
 | 
			
		||||
	else {
 | 
			
		||||
		printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
 | 
			
		||||
		       "from remote control\n", code);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	input_report_key(fdtv->remote_ctrl_dev, code, 1);
 | 
			
		||||
	input_report_key(fdtv->remote_ctrl_dev, code, 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										182
									
								
								drivers/media/dvb/firewire/firedtv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								drivers/media/dvb/firewire/firedtv.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,182 @@
 | 
			
		|||
/*
 | 
			
		||||
 * FireDTV driver (formerly known as FireSAT)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
 | 
			
		||||
 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
 | 
			
		||||
 *
 | 
			
		||||
 *	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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _FIREDTV_H
 | 
			
		||||
#define _FIREDTV_H
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
#include <linux/dvb/frontend.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/spinlock_types.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/wait.h>
 | 
			
		||||
#include <linux/workqueue.h>
 | 
			
		||||
 | 
			
		||||
#include <demux.h>
 | 
			
		||||
#include <dmxdev.h>
 | 
			
		||||
#include <dvb_demux.h>
 | 
			
		||||
#include <dvb_frontend.h>
 | 
			
		||||
#include <dvb_net.h>
 | 
			
		||||
#include <dvbdev.h>
 | 
			
		||||
 | 
			
		||||
struct firedtv_tuner_status {
 | 
			
		||||
	unsigned active_system:8;
 | 
			
		||||
	unsigned searching:1;
 | 
			
		||||
	unsigned moving:1;
 | 
			
		||||
	unsigned no_rf:1;
 | 
			
		||||
	unsigned input:1;
 | 
			
		||||
	unsigned selected_antenna:7;
 | 
			
		||||
	unsigned ber:32;
 | 
			
		||||
	unsigned signal_strength:8;
 | 
			
		||||
	unsigned raster_frequency:2;
 | 
			
		||||
	unsigned rf_frequency:22;
 | 
			
		||||
	unsigned man_dep_info_length:8;
 | 
			
		||||
	unsigned front_end_error:1;
 | 
			
		||||
	unsigned antenna_error:1;
 | 
			
		||||
	unsigned front_end_power_status:1;
 | 
			
		||||
	unsigned power_supply:1;
 | 
			
		||||
	unsigned carrier_noise_ratio:16;
 | 
			
		||||
	unsigned power_supply_voltage:8;
 | 
			
		||||
	unsigned antenna_voltage:8;
 | 
			
		||||
	unsigned firewire_bus_voltage:8;
 | 
			
		||||
	unsigned ca_mmi:1;
 | 
			
		||||
	unsigned ca_pmt_reply:1;
 | 
			
		||||
	unsigned ca_date_time_request:1;
 | 
			
		||||
	unsigned ca_application_info:1;
 | 
			
		||||
	unsigned ca_module_present_status:1;
 | 
			
		||||
	unsigned ca_dvb_flag:1;
 | 
			
		||||
	unsigned ca_error_flag:1;
 | 
			
		||||
	unsigned ca_initialization_status:1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum model_type {
 | 
			
		||||
	FIREDTV_UNKNOWN = 0,
 | 
			
		||||
	FIREDTV_DVB_S   = 1,
 | 
			
		||||
	FIREDTV_DVB_C   = 2,
 | 
			
		||||
	FIREDTV_DVB_T   = 3,
 | 
			
		||||
	FIREDTV_DVB_S2  = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct device;
 | 
			
		||||
struct input_dev;
 | 
			
		||||
struct firedtv;
 | 
			
		||||
 | 
			
		||||
struct firedtv_backend {
 | 
			
		||||
	int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
 | 
			
		||||
	int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 | 
			
		||||
	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 | 
			
		||||
	int (*start_iso)(struct firedtv *fdtv);
 | 
			
		||||
	void (*stop_iso)(struct firedtv *fdtv);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct firedtv {
 | 
			
		||||
	struct device *device;
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
 | 
			
		||||
	struct dvb_adapter	adapter;
 | 
			
		||||
	struct dmxdev		dmxdev;
 | 
			
		||||
	struct dvb_demux	demux;
 | 
			
		||||
	struct dmx_frontend	frontend;
 | 
			
		||||
	struct dvb_net		dvbnet;
 | 
			
		||||
	struct dvb_frontend	fe;
 | 
			
		||||
 | 
			
		||||
	struct dvb_device	*cadev;
 | 
			
		||||
	int			ca_last_command;
 | 
			
		||||
	int			ca_time_interval;
 | 
			
		||||
 | 
			
		||||
	struct mutex		avc_mutex;
 | 
			
		||||
	wait_queue_head_t	avc_wait;
 | 
			
		||||
	bool			avc_reply_received;
 | 
			
		||||
	struct work_struct	remote_ctrl_work;
 | 
			
		||||
	struct input_dev	*remote_ctrl_dev;
 | 
			
		||||
 | 
			
		||||
	enum model_type		type;
 | 
			
		||||
	char			subunit;
 | 
			
		||||
	char			isochannel;
 | 
			
		||||
	fe_sec_voltage_t	voltage;
 | 
			
		||||
	fe_sec_tone_mode_t	tone;
 | 
			
		||||
 | 
			
		||||
	const struct firedtv_backend *backend;
 | 
			
		||||
	void			*backend_data;
 | 
			
		||||
 | 
			
		||||
	struct mutex		demux_mutex;
 | 
			
		||||
	unsigned long		channel_active;
 | 
			
		||||
	u16			channel_pid[16];
 | 
			
		||||
 | 
			
		||||
	size_t			response_length;
 | 
			
		||||
	u8			response[512];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* firedtv-1394.c */
 | 
			
		||||
#ifdef CONFIG_DVB_FIREDTV_IEEE1394
 | 
			
		||||
int fdtv_1394_init(struct ieee1394_device_id id_table[]);
 | 
			
		||||
void fdtv_1394_exit(void);
 | 
			
		||||
#else
 | 
			
		||||
static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
 | 
			
		||||
static inline void fdtv_1394_exit(void) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* firedtv-avc.c */
 | 
			
		||||
int avc_recv(struct firedtv *fdtv, void *data, size_t length);
 | 
			
		||||
int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
 | 
			
		||||
struct dvb_frontend_parameters;
 | 
			
		||||
int avc_tuner_dsd(struct firedtv *fdtv, struct dvb_frontend_parameters *params);
 | 
			
		||||
int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
 | 
			
		||||
int avc_tuner_get_ts(struct firedtv *fdtv);
 | 
			
		||||
int avc_identify_subunit(struct firedtv *fdtv);
 | 
			
		||||
struct dvb_diseqc_master_cmd;
 | 
			
		||||
int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
 | 
			
		||||
		    char conttone, char nrdiseq,
 | 
			
		||||
		    struct dvb_diseqc_master_cmd *diseqcmd);
 | 
			
		||||
void avc_remote_ctrl_work(struct work_struct *work);
 | 
			
		||||
int avc_register_remote_control(struct firedtv *fdtv);
 | 
			
		||||
int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
 | 
			
		||||
int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
 | 
			
		||||
int avc_ca_reset(struct firedtv *fdtv);
 | 
			
		||||
int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
 | 
			
		||||
int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
 | 
			
		||||
int avc_ca_enter_menu(struct firedtv *fdtv);
 | 
			
		||||
int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
 | 
			
		||||
int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
 | 
			
		||||
void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
 | 
			
		||||
 | 
			
		||||
/* firedtv-ci.c */
 | 
			
		||||
int fdtv_ca_register(struct firedtv *fdtv);
 | 
			
		||||
void fdtv_ca_release(struct firedtv *fdtv);
 | 
			
		||||
 | 
			
		||||
/* firedtv-dvb.c */
 | 
			
		||||
int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
 | 
			
		||||
int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
 | 
			
		||||
int fdtv_dvb_register(struct firedtv *fdtv);
 | 
			
		||||
void fdtv_dvb_unregister(struct firedtv *fdtv);
 | 
			
		||||
struct firedtv *fdtv_alloc(struct device *dev,
 | 
			
		||||
			   const struct firedtv_backend *backend,
 | 
			
		||||
			   const char *name, size_t name_len);
 | 
			
		||||
extern const char *fdtv_model_names[];
 | 
			
		||||
 | 
			
		||||
/* firedtv-fe.c */
 | 
			
		||||
void fdtv_frontend_init(struct firedtv *fdtv);
 | 
			
		||||
 | 
			
		||||
/* firedtv-rc.c */
 | 
			
		||||
#ifdef CONFIG_DVB_FIREDTV_INPUT
 | 
			
		||||
int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
 | 
			
		||||
void fdtv_unregister_rc(struct firedtv *fdtv);
 | 
			
		||||
void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
 | 
			
		||||
#else
 | 
			
		||||
static inline int fdtv_register_rc(struct firedtv *fdtv,
 | 
			
		||||
				   struct device *dev) { return 0; }
 | 
			
		||||
static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
 | 
			
		||||
static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _FIREDTV_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -2342,6 +2342,17 @@ config ATL1E
 | 
			
		|||
	  To compile this driver as a module, choose M here.  The module
 | 
			
		||||
	  will be called atl1e.
 | 
			
		||||
 | 
			
		||||
config ATL1C
 | 
			
		||||
	tristate "Atheros L1C Gigabit Ethernet support (EXPERIMENTAL)"
 | 
			
		||||
	depends on PCI && EXPERIMENTAL
 | 
			
		||||
	select CRC32
 | 
			
		||||
	select MII
 | 
			
		||||
	help
 | 
			
		||||
	  This driver supports the Atheros L1C gigabit ethernet adapter.
 | 
			
		||||
 | 
			
		||||
	  To compile this driver as a module, choose M here.  The module
 | 
			
		||||
	  will be called atl1c.
 | 
			
		||||
 | 
			
		||||
config JME
 | 
			
		||||
	tristate "JMicron(R) PCI-Express Gigabit Ethernet support"
 | 
			
		||||
	depends on PCI
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ obj-$(CONFIG_BONDING) += bonding/
 | 
			
		|||
obj-$(CONFIG_ATL1) += atlx/
 | 
			
		||||
obj-$(CONFIG_ATL2) += atlx/
 | 
			
		||||
obj-$(CONFIG_ATL1E) += atl1e/
 | 
			
		||||
obj-$(CONFIG_ATL1C) += atl1c/
 | 
			
		||||
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
 | 
			
		||||
obj-$(CONFIG_TEHUTI) += tehuti.o
 | 
			
		||||
obj-$(CONFIG_ENIC) += enic/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								drivers/net/atl1c/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								drivers/net/atl1c/Makefile
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
obj-$(CONFIG_ATL1C) += atl1c.o
 | 
			
		||||
atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o
 | 
			
		||||
							
								
								
									
										606
									
								
								drivers/net/atl1c/atl1c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										606
									
								
								drivers/net/atl1c/atl1c.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,606 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Derived from Intel e1000 driver
 | 
			
		||||
 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
 * Software Foundation; either version 2 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ATL1C_H_
 | 
			
		||||
#define _ATL1C_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/version.h>
 | 
			
		||||
#include <linux/init.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/pci.h>
 | 
			
		||||
#include <linux/netdevice.h>
 | 
			
		||||
#include <linux/etherdevice.h>
 | 
			
		||||
#include <linux/skbuff.h>
 | 
			
		||||
#include <linux/ioport.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include <linux/in.h>
 | 
			
		||||
#include <linux/ip.h>
 | 
			
		||||
#include <linux/ipv6.h>
 | 
			
		||||
#include <linux/udp.h>
 | 
			
		||||
#include <linux/mii.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <linux/vmalloc.h>
 | 
			
		||||
#include <linux/pagemap.h>
 | 
			
		||||
#include <linux/tcp.h>
 | 
			
		||||
#include <linux/mii.h>
 | 
			
		||||
#include <linux/ethtool.h>
 | 
			
		||||
#include <linux/if_vlan.h>
 | 
			
		||||
#include <linux/workqueue.h>
 | 
			
		||||
#include <net/checksum.h>
 | 
			
		||||
#include <net/ip6_checksum.h>
 | 
			
		||||
 | 
			
		||||
#include "atl1c_hw.h"
 | 
			
		||||
 | 
			
		||||
/* Wake Up Filter Control */
 | 
			
		||||
#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
 | 
			
		||||
#define AT_WUFC_MAG  0x00000002 /* Magic Packet Wakeup Enable */
 | 
			
		||||
#define AT_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
 | 
			
		||||
#define AT_WUFC_MC   0x00000008 /* Multicast Wakeup Enable */
 | 
			
		||||
#define AT_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
 | 
			
		||||
 | 
			
		||||
#define AT_VLAN_TO_TAG(_vlan, _tag)	   \
 | 
			
		||||
	_tag =  ((((_vlan) >> 8) & 0xFF)  |\
 | 
			
		||||
		 (((_vlan) & 0xFF) << 8))
 | 
			
		||||
 | 
			
		||||
#define AT_TAG_TO_VLAN(_tag, _vlan) 	 \
 | 
			
		||||
	_vlan = ((((_tag) >> 8) & 0xFF) |\
 | 
			
		||||
		(((_tag) & 0xFF) << 8))
 | 
			
		||||
 | 
			
		||||
#define SPEED_0		   0xffff
 | 
			
		||||
#define HALF_DUPLEX        1
 | 
			
		||||
#define FULL_DUPLEX        2
 | 
			
		||||
 | 
			
		||||
#define AT_RX_BUF_SIZE		(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)
 | 
			
		||||
#define MAX_JUMBO_FRAME_SIZE 	(9*1024)
 | 
			
		||||
#define MAX_TX_OFFLOAD_THRESH	(9*1024)
 | 
			
		||||
 | 
			
		||||
#define AT_MAX_RECEIVE_QUEUE    4
 | 
			
		||||
#define AT_DEF_RECEIVE_QUEUE	1
 | 
			
		||||
#define AT_MAX_TRANSMIT_QUEUE	2
 | 
			
		||||
 | 
			
		||||
#define AT_DMA_HI_ADDR_MASK     0xffffffff00000000ULL
 | 
			
		||||
#define AT_DMA_LO_ADDR_MASK     0x00000000ffffffffULL
 | 
			
		||||
 | 
			
		||||
#define AT_TX_WATCHDOG  (5 * HZ)
 | 
			
		||||
#define AT_MAX_INT_WORK		5
 | 
			
		||||
#define AT_TWSI_EEPROM_TIMEOUT 	100
 | 
			
		||||
#define AT_HW_MAX_IDLE_DELAY 	10
 | 
			
		||||
#define AT_SUSPEND_LINK_TIMEOUT 28
 | 
			
		||||
 | 
			
		||||
#define AT_ASPM_L0S_TIMER	6
 | 
			
		||||
#define AT_ASPM_L1_TIMER	12
 | 
			
		||||
 | 
			
		||||
#define ATL1C_PCIE_L0S_L1_DISABLE 	0x01
 | 
			
		||||
#define ATL1C_PCIE_PHY_RESET		0x02
 | 
			
		||||
 | 
			
		||||
#define ATL1C_ASPM_L0s_ENABLE		0x0001
 | 
			
		||||
#define ATL1C_ASPM_L1_ENABLE		0x0002
 | 
			
		||||
 | 
			
		||||
#define AT_REGS_LEN	(75 * sizeof(u32))
 | 
			
		||||
#define AT_EEPROM_LEN 	512
 | 
			
		||||
 | 
			
		||||
#define ATL1C_GET_DESC(R, i, type)	(&(((type *)((R)->desc))[i]))
 | 
			
		||||
#define ATL1C_RFD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc)
 | 
			
		||||
#define ATL1C_TPD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc)
 | 
			
		||||
#define ATL1C_RRD_DESC(R, i)	ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status)
 | 
			
		||||
 | 
			
		||||
/* tpd word 1 bit 0:7 General Checksum task offload */
 | 
			
		||||
#define TPD_L4HDR_OFFSET_MASK	0x00FF
 | 
			
		||||
#define TPD_L4HDR_OFFSET_SHIFT	0
 | 
			
		||||
 | 
			
		||||
/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */
 | 
			
		||||
#define TPD_TCPHDR_OFFSET_MASK	0x00FF
 | 
			
		||||
#define TPD_TCPHDR_OFFSET_SHIFT	0
 | 
			
		||||
 | 
			
		||||
/* tpd word 1 bit 0:7 Custom Checksum task offload */
 | 
			
		||||
#define TPD_PLOADOFFSET_MASK	0x00FF
 | 
			
		||||
#define TPD_PLOADOFFSET_SHIFT	0
 | 
			
		||||
 | 
			
		||||
/* tpd word 1 bit 8:17 */
 | 
			
		||||
#define TPD_CCSUM_EN_MASK	0x0001
 | 
			
		||||
#define TPD_CCSUM_EN_SHIFT	8
 | 
			
		||||
#define TPD_IP_CSUM_MASK	0x0001
 | 
			
		||||
#define TPD_IP_CSUM_SHIFT	9
 | 
			
		||||
#define TPD_TCP_CSUM_MASK	0x0001
 | 
			
		||||
#define TPD_TCP_CSUM_SHIFT	10
 | 
			
		||||
#define TPD_UDP_CSUM_MASK	0x0001
 | 
			
		||||
#define TPD_UDP_CSUM_SHIFT	11
 | 
			
		||||
#define TPD_LSO_EN_MASK		0x0001	/* TCP Large Send Offload */
 | 
			
		||||
#define TPD_LSO_EN_SHIFT	12
 | 
			
		||||
#define TPD_LSO_VER_MASK	0x0001
 | 
			
		||||
#define TPD_LSO_VER_SHIFT	13 	/* 0 : ipv4; 1 : ipv4/ipv6 */
 | 
			
		||||
#define TPD_CON_VTAG_MASK	0x0001
 | 
			
		||||
#define TPD_CON_VTAG_SHIFT	14
 | 
			
		||||
#define TPD_INS_VTAG_MASK	0x0001
 | 
			
		||||
#define TPD_INS_VTAG_SHIFT	15
 | 
			
		||||
#define TPD_IPV4_PACKET_MASK	0x0001  /* valid when LSO VER  is 1 */
 | 
			
		||||
#define TPD_IPV4_PACKET_SHIFT	16
 | 
			
		||||
#define TPD_ETH_TYPE_MASK	0x0001
 | 
			
		||||
#define TPD_ETH_TYPE_SHIFT	17	/* 0 : 802.3 frame; 1 : Ethernet */
 | 
			
		||||
 | 
			
		||||
/* tpd word 18:25 Custom Checksum task offload */
 | 
			
		||||
#define TPD_CCSUM_OFFSET_MASK	0x00FF
 | 
			
		||||
#define TPD_CCSUM_OFFSET_SHIFT	18
 | 
			
		||||
#define TPD_CCSUM_EPAD_MASK	0x0001
 | 
			
		||||
#define TPD_CCSUM_EPAD_SHIFT	30
 | 
			
		||||
 | 
			
		||||
/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */
 | 
			
		||||
#define TPD_MSS_MASK            0x1FFF
 | 
			
		||||
#define TPD_MSS_SHIFT		18
 | 
			
		||||
 | 
			
		||||
#define TPD_EOP_MASK		0x0001
 | 
			
		||||
#define TPD_EOP_SHIFT		31
 | 
			
		||||
 | 
			
		||||
struct atl1c_tpd_desc {
 | 
			
		||||
	__le16	buffer_len; /* include 4-byte CRC */
 | 
			
		||||
	__le16	vlan_tag;
 | 
			
		||||
	__le32	word1;
 | 
			
		||||
	__le64	buffer_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct atl1c_tpd_ext_desc {
 | 
			
		||||
	u32 reservd_0;
 | 
			
		||||
	__le32 word1;
 | 
			
		||||
	__le32 pkt_len;
 | 
			
		||||
	u32 reservd_1;
 | 
			
		||||
};
 | 
			
		||||
/* rrs word 0 bit 0:31 */
 | 
			
		||||
#define RRS_RX_CSUM_MASK	0xFFFF
 | 
			
		||||
#define RRS_RX_CSUM_SHIFT	0
 | 
			
		||||
#define RRS_RX_RFD_CNT_MASK	0x000F
 | 
			
		||||
#define RRS_RX_RFD_CNT_SHIFT	16
 | 
			
		||||
#define RRS_RX_RFD_INDEX_MASK	0x0FFF
 | 
			
		||||
#define RRS_RX_RFD_INDEX_SHIFT	20
 | 
			
		||||
 | 
			
		||||
/* rrs flag bit 0:16 */
 | 
			
		||||
#define RRS_HEAD_LEN_MASK	0x00FF
 | 
			
		||||
#define RRS_HEAD_LEN_SHIFT	0
 | 
			
		||||
#define RRS_HDS_TYPE_MASK	0x0003
 | 
			
		||||
#define RRS_HDS_TYPE_SHIFT	8
 | 
			
		||||
#define RRS_CPU_NUM_MASK	0x0003
 | 
			
		||||
#define	RRS_CPU_NUM_SHIFT	10
 | 
			
		||||
#define RRS_HASH_FLG_MASK	0x000F
 | 
			
		||||
#define RRS_HASH_FLG_SHIFT	12
 | 
			
		||||
 | 
			
		||||
#define RRS_HDS_TYPE_HEAD	1
 | 
			
		||||
#define RRS_HDS_TYPE_DATA	2
 | 
			
		||||
 | 
			
		||||
#define RRS_IS_NO_HDS_TYPE(flag) \
 | 
			
		||||
	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
 | 
			
		||||
 | 
			
		||||
#define RRS_IS_HDS_HEAD(flag) \
 | 
			
		||||
	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
 | 
			
		||||
			RRS_HDS_TYPE_HEAD)
 | 
			
		||||
 | 
			
		||||
#define RRS_IS_HDS_DATA(flag) \
 | 
			
		||||
	(((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
 | 
			
		||||
			RRS_HDS_TYPE_DATA)
 | 
			
		||||
 | 
			
		||||
/* rrs word 3 bit 0:31 */
 | 
			
		||||
#define RRS_PKT_SIZE_MASK	0x3FFF
 | 
			
		||||
#define RRS_PKT_SIZE_SHIFT	0
 | 
			
		||||
#define RRS_ERR_L4_CSUM_MASK	0x0001
 | 
			
		||||
#define RRS_ERR_L4_CSUM_SHIFT	14
 | 
			
		||||
#define RRS_ERR_IP_CSUM_MASK	0x0001
 | 
			
		||||
#define RRS_ERR_IP_CSUM_SHIFT	15
 | 
			
		||||
#define RRS_VLAN_INS_MASK	0x0001
 | 
			
		||||
#define RRS_VLAN_INS_SHIFT	16
 | 
			
		||||
#define RRS_PROT_ID_MASK	0x0007
 | 
			
		||||
#define RRS_PROT_ID_SHIFT	17
 | 
			
		||||
#define RRS_RX_ERR_SUM_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_SUM_SHIFT	20
 | 
			
		||||
#define RRS_RX_ERR_CRC_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_CRC_SHIFT	21
 | 
			
		||||
#define RRS_RX_ERR_FAE_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_FAE_SHIFT	22
 | 
			
		||||
#define RRS_RX_ERR_TRUNC_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_TRUNC_SHIFT	23
 | 
			
		||||
#define RRS_RX_ERR_RUNC_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_RUNC_SHIFT	24
 | 
			
		||||
#define RRS_RX_ERR_ICMP_MASK	0x0001
 | 
			
		||||
#define RRS_RX_ERR_ICMP_SHIFT	25
 | 
			
		||||
#define RRS_PACKET_BCAST_MASK	0x0001
 | 
			
		||||
#define RRS_PACKET_BCAST_SHIFT	26
 | 
			
		||||
#define RRS_PACKET_MCAST_MASK	0x0001
 | 
			
		||||
#define RRS_PACKET_MCAST_SHIFT	27
 | 
			
		||||
#define RRS_PACKET_TYPE_MASK	0x0001
 | 
			
		||||
#define RRS_PACKET_TYPE_SHIFT	28
 | 
			
		||||
#define RRS_FIFO_FULL_MASK	0x0001
 | 
			
		||||
#define RRS_FIFO_FULL_SHIFT	29
 | 
			
		||||
#define RRS_802_3_LEN_ERR_MASK 	0x0001
 | 
			
		||||
#define RRS_802_3_LEN_ERR_SHIFT 30
 | 
			
		||||
#define RRS_RXD_UPDATED_MASK	0x0001
 | 
			
		||||
#define RRS_RXD_UPDATED_SHIFT	31
 | 
			
		||||
 | 
			
		||||
#define RRS_ERR_L4_CSUM         0x00004000
 | 
			
		||||
#define RRS_ERR_IP_CSUM         0x00008000
 | 
			
		||||
#define RRS_VLAN_INS            0x00010000
 | 
			
		||||
#define RRS_RX_ERR_SUM          0x00100000
 | 
			
		||||
#define RRS_RX_ERR_CRC          0x00200000
 | 
			
		||||
#define RRS_802_3_LEN_ERR	0x40000000
 | 
			
		||||
#define RRS_RXD_UPDATED		0x80000000
 | 
			
		||||
 | 
			
		||||
#define RRS_PACKET_TYPE_802_3  	1
 | 
			
		||||
#define RRS_PACKET_TYPE_ETH	0
 | 
			
		||||
#define RRS_PACKET_IS_ETH(word) \
 | 
			
		||||
	(((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \
 | 
			
		||||
			RRS_PACKET_TYPE_ETH)
 | 
			
		||||
#define RRS_RXD_IS_VALID(word) \
 | 
			
		||||
	((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
 | 
			
		||||
 | 
			
		||||
#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \
 | 
			
		||||
	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1)
 | 
			
		||||
#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \
 | 
			
		||||
	((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6)
 | 
			
		||||
 | 
			
		||||
struct atl1c_recv_ret_status {
 | 
			
		||||
	__le32  word0;
 | 
			
		||||
	__le32	rss_hash;
 | 
			
		||||
	__le16	vlan_tag;
 | 
			
		||||
	__le16	flag;
 | 
			
		||||
	__le32	word3;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* RFD desciptor */
 | 
			
		||||
struct atl1c_rx_free_desc {
 | 
			
		||||
	__le64	buffer_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* DMA Order Settings */
 | 
			
		||||
enum atl1c_dma_order {
 | 
			
		||||
	atl1c_dma_ord_in = 1,
 | 
			
		||||
	atl1c_dma_ord_enh = 2,
 | 
			
		||||
	atl1c_dma_ord_out = 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_dma_rcb {
 | 
			
		||||
	atl1c_rcb_64 = 0,
 | 
			
		||||
	atl1c_rcb_128 = 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_mac_speed {
 | 
			
		||||
	atl1c_mac_speed_0 = 0,
 | 
			
		||||
	atl1c_mac_speed_10_100 = 1,
 | 
			
		||||
	atl1c_mac_speed_1000 = 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_dma_req_block {
 | 
			
		||||
	atl1c_dma_req_128 = 0,
 | 
			
		||||
	atl1c_dma_req_256 = 1,
 | 
			
		||||
	atl1c_dma_req_512 = 2,
 | 
			
		||||
	atl1c_dma_req_1024 = 3,
 | 
			
		||||
	atl1c_dma_req_2048 = 4,
 | 
			
		||||
	atl1c_dma_req_4096 = 5
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_rss_mode {
 | 
			
		||||
	atl1c_rss_mode_disable = 0,
 | 
			
		||||
	atl1c_rss_sig_que = 1,
 | 
			
		||||
	atl1c_rss_mul_que_sig_int = 2,
 | 
			
		||||
	atl1c_rss_mul_que_mul_int = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_rss_type {
 | 
			
		||||
	atl1c_rss_disable = 0,
 | 
			
		||||
	atl1c_rss_ipv4 = 1,
 | 
			
		||||
	atl1c_rss_ipv4_tcp = 2,
 | 
			
		||||
	atl1c_rss_ipv6 = 4,
 | 
			
		||||
	atl1c_rss_ipv6_tcp = 8
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_nic_type {
 | 
			
		||||
	athr_l1c = 0,
 | 
			
		||||
	athr_l2c = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum atl1c_trans_queue {
 | 
			
		||||
	atl1c_trans_normal = 0,
 | 
			
		||||
	atl1c_trans_high = 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct atl1c_hw_stats {
 | 
			
		||||
	/* rx */
 | 
			
		||||
	unsigned long rx_ok;		/* The number of good packet received. */
 | 
			
		||||
	unsigned long rx_bcast;		/* The number of good broadcast packet received. */
 | 
			
		||||
	unsigned long rx_mcast;		/* The number of good multicast packet received. */
 | 
			
		||||
	unsigned long rx_pause;		/* The number of Pause packet received. */
 | 
			
		||||
	unsigned long rx_ctrl;		/* The number of Control packet received other than Pause frame. */
 | 
			
		||||
	unsigned long rx_fcs_err;	/* The number of packets with bad FCS. */
 | 
			
		||||
	unsigned long rx_len_err;	/* The number of packets with mismatch of length field and actual size. */
 | 
			
		||||
	unsigned long rx_byte_cnt;	/* The number of bytes of good packet received. FCS is NOT included. */
 | 
			
		||||
	unsigned long rx_runt;		/* The number of packets received that are less than 64 byte long and with good FCS. */
 | 
			
		||||
	unsigned long rx_frag;		/* The number of packets received that are less than 64 byte long and with bad FCS. */
 | 
			
		||||
	unsigned long rx_sz_64;		/* The number of good and bad packets received that are 64 byte long. */
 | 
			
		||||
	unsigned long rx_sz_65_127;	/* The number of good and bad packets received that are between 65 and 127-byte long. */
 | 
			
		||||
	unsigned long rx_sz_128_255;	/* The number of good and bad packets received that are between 128 and 255-byte long. */
 | 
			
		||||
	unsigned long rx_sz_256_511;	/* The number of good and bad packets received that are between 256 and 511-byte long. */
 | 
			
		||||
	unsigned long rx_sz_512_1023;	/* The number of good and bad packets received that are between 512 and 1023-byte long. */
 | 
			
		||||
	unsigned long rx_sz_1024_1518;	/* The number of good and bad packets received that are between 1024 and 1518-byte long. */
 | 
			
		||||
	unsigned long rx_sz_1519_max;	/* The number of good and bad packets received that are between 1519-byte and MTU. */
 | 
			
		||||
	unsigned long rx_sz_ov;		/* The number of good and bad packets received that are more than MTU size truncated by Selene. */
 | 
			
		||||
	unsigned long rx_rxf_ov;	/* The number of frame dropped due to occurrence of RX FIFO overflow. */
 | 
			
		||||
	unsigned long rx_rrd_ov;	/* The number of frame dropped due to occurrence of RRD overflow. */
 | 
			
		||||
	unsigned long rx_align_err;	/* Alignment Error */
 | 
			
		||||
	unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */
 | 
			
		||||
	unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */
 | 
			
		||||
	unsigned long rx_err_addr;	/* The number of packets dropped due to address filtering. */
 | 
			
		||||
 | 
			
		||||
	/* tx */
 | 
			
		||||
	unsigned long tx_ok;		/* The number of good packet transmitted. */
 | 
			
		||||
	unsigned long tx_bcast;		/* The number of good broadcast packet transmitted. */
 | 
			
		||||
	unsigned long tx_mcast;		/* The number of good multicast packet transmitted. */
 | 
			
		||||
	unsigned long tx_pause;		/* The number of Pause packet transmitted. */
 | 
			
		||||
	unsigned long tx_exc_defer;	/* The number of packets transmitted with excessive deferral. */
 | 
			
		||||
	unsigned long tx_ctrl;		/* The number of packets transmitted is a control frame, excluding Pause frame. */
 | 
			
		||||
	unsigned long tx_defer;		/* The number of packets transmitted that is deferred. */
 | 
			
		||||
	unsigned long tx_byte_cnt;	/* The number of bytes of data transmitted. FCS is NOT included. */
 | 
			
		||||
	unsigned long tx_sz_64;		/* The number of good and bad packets transmitted that are 64 byte long. */
 | 
			
		||||
	unsigned long tx_sz_65_127;	/* The number of good and bad packets transmitted that are between 65 and 127-byte long. */
 | 
			
		||||
	unsigned long tx_sz_128_255;	/* The number of good and bad packets transmitted that are between 128 and 255-byte long. */
 | 
			
		||||
	unsigned long tx_sz_256_511;	/* The number of good and bad packets transmitted that are between 256 and 511-byte long. */
 | 
			
		||||
	unsigned long tx_sz_512_1023;	/* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */
 | 
			
		||||
	unsigned long tx_sz_1024_1518;	/* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */
 | 
			
		||||
	unsigned long tx_sz_1519_max;	/* The number of good and bad packets transmitted that are between 1519-byte and MTU. */
 | 
			
		||||
	unsigned long tx_1_col;		/* The number of packets subsequently transmitted successfully with a single prior collision. */
 | 
			
		||||
	unsigned long tx_2_col;		/* The number of packets subsequently transmitted successfully with multiple prior collisions. */
 | 
			
		||||
	unsigned long tx_late_col;	/* The number of packets transmitted with late collisions. */
 | 
			
		||||
	unsigned long tx_abort_col;	/* The number of transmit packets aborted due to excessive collisions. */
 | 
			
		||||
	unsigned long tx_underrun;	/* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */
 | 
			
		||||
	unsigned long tx_rd_eop;	/* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */
 | 
			
		||||
	unsigned long tx_len_err;	/* The number of transmit packets with length field does NOT match the actual frame size. */
 | 
			
		||||
	unsigned long tx_trunc;		/* The number of transmit packets truncated due to size exceeding MTU. */
 | 
			
		||||
	unsigned long tx_bcast_byte;	/* The byte count of broadcast packet transmitted, excluding FCS. */
 | 
			
		||||
	unsigned long tx_mcast_byte;	/* The byte count of multicast packet transmitted, excluding FCS. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct atl1c_hw {
 | 
			
		||||
	u8 __iomem      *hw_addr;            /* inner register address */
 | 
			
		||||
	struct atl1c_adapter *adapter;
 | 
			
		||||
	enum atl1c_nic_type  nic_type;
 | 
			
		||||
	enum atl1c_dma_order dma_order;
 | 
			
		||||
	enum atl1c_dma_rcb   rcb_value;
 | 
			
		||||
	enum atl1c_dma_req_block dmar_block;
 | 
			
		||||
	enum atl1c_dma_req_block dmaw_block;
 | 
			
		||||
 | 
			
		||||
	u16 device_id;
 | 
			
		||||
	u16 vendor_id;
 | 
			
		||||
	u16 subsystem_id;
 | 
			
		||||
	u16 subsystem_vendor_id;
 | 
			
		||||
	u8 revision_id;
 | 
			
		||||
 | 
			
		||||
	u32 intr_mask;
 | 
			
		||||
	u8 dmaw_dly_cnt;
 | 
			
		||||
	u8 dmar_dly_cnt;
 | 
			
		||||
 | 
			
		||||
	u8 preamble_len;
 | 
			
		||||
	u16 max_frame_size;
 | 
			
		||||
	u16 min_frame_size;
 | 
			
		||||
 | 
			
		||||
	enum atl1c_mac_speed mac_speed;
 | 
			
		||||
	bool mac_duplex;
 | 
			
		||||
	bool hibernate;
 | 
			
		||||
	u16 media_type;
 | 
			
		||||
#define MEDIA_TYPE_AUTO_SENSOR  0
 | 
			
		||||
#define MEDIA_TYPE_100M_FULL    1
 | 
			
		||||
#define MEDIA_TYPE_100M_HALF    2
 | 
			
		||||
#define MEDIA_TYPE_10M_FULL     3
 | 
			
		||||
#define MEDIA_TYPE_10M_HALF     4
 | 
			
		||||
 | 
			
		||||
	u16 autoneg_advertised;
 | 
			
		||||
	u16 mii_autoneg_adv_reg;
 | 
			
		||||
	u16 mii_1000t_ctrl_reg;
 | 
			
		||||
 | 
			
		||||
	u16 tx_imt;	/* TX Interrupt Moderator timer ( 2us resolution) */
 | 
			
		||||
	u16 rx_imt;	/* RX Interrupt Moderator timer ( 2us resolution) */
 | 
			
		||||
	u16 ict;        /* Interrupt Clear timer (2us resolution) */
 | 
			
		||||
	u16 ctrl_flags;
 | 
			
		||||
#define ATL1C_INTR_CLEAR_ON_READ	0x0001
 | 
			
		||||
#define ATL1C_INTR_MODRT_ENABLE	 	0x0002
 | 
			
		||||
#define ATL1C_CMB_ENABLE		0x0004
 | 
			
		||||
#define ATL1C_SMB_ENABLE		0x0010
 | 
			
		||||
#define ATL1C_TXQ_MODE_ENHANCE		0x0020
 | 
			
		||||
#define ATL1C_RX_IPV6_CHKSUM		0x0040
 | 
			
		||||
#define ATL1C_ASPM_L0S_SUPPORT		0x0080
 | 
			
		||||
#define ATL1C_ASPM_L1_SUPPORT		0x0100
 | 
			
		||||
#define ATL1C_ASPM_CTRL_MON		0x0200
 | 
			
		||||
#define ATL1C_HIB_DISABLE		0x0400
 | 
			
		||||
#define ATL1C_LINK_CAP_1000M		0x0800
 | 
			
		||||
#define ATL1C_FPGA_VERSION		0x8000
 | 
			
		||||
	u16 cmb_tpd;
 | 
			
		||||
	u16 cmb_rrd;
 | 
			
		||||
	u16 cmb_rx_timer; /* 2us resolution */
 | 
			
		||||
	u16 cmb_tx_timer;
 | 
			
		||||
	u32 smb_timer;
 | 
			
		||||
 | 
			
		||||
	u16 rrd_thresh; /* Threshold of number of RRD produced to trigger
 | 
			
		||||
			  interrupt request */
 | 
			
		||||
	u16 tpd_thresh;
 | 
			
		||||
	u8 tpd_burst;   /* Number of TPD to prefetch in cache-aligned burst. */
 | 
			
		||||
	u8 rfd_burst;
 | 
			
		||||
	enum atl1c_rss_type rss_type;
 | 
			
		||||
	enum atl1c_rss_mode rss_mode;
 | 
			
		||||
	u8 rss_hash_bits;
 | 
			
		||||
	u32 base_cpu;
 | 
			
		||||
	u32 indirect_tab;
 | 
			
		||||
	u8 mac_addr[ETH_ALEN];
 | 
			
		||||
	u8 perm_mac_addr[ETH_ALEN];
 | 
			
		||||
 | 
			
		||||
	bool phy_configured;
 | 
			
		||||
	bool re_autoneg;
 | 
			
		||||
	bool emi_ca;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * atl1c_ring_header represents a single, contiguous block of DMA space
 | 
			
		||||
 * mapped for the three descriptor rings (tpd, rfd, rrd) and the two
 | 
			
		||||
 * message blocks (cmb, smb) described below
 | 
			
		||||
 */
 | 
			
		||||
struct atl1c_ring_header {
 | 
			
		||||
	void *desc;		/* virtual address */
 | 
			
		||||
	dma_addr_t dma;		/* physical address*/
 | 
			
		||||
	unsigned int size;	/* length in bytes */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * atl1c_buffer is wrapper around a pointer to a socket buffer
 | 
			
		||||
 * so a DMA handle can be stored along with the skb
 | 
			
		||||
 */
 | 
			
		||||
struct atl1c_buffer {
 | 
			
		||||
	struct sk_buff *skb;	/* socket buffer */
 | 
			
		||||
	u16 length;		/* rx buffer length */
 | 
			
		||||
	u16 state;		/* state of buffer */
 | 
			
		||||
#define ATL1_BUFFER_FREE	0
 | 
			
		||||
#define ATL1_BUFFER_BUSY	1
 | 
			
		||||
	dma_addr_t dma;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* transimit packet descriptor (tpd) ring */
 | 
			
		||||
struct atl1c_tpd_ring {
 | 
			
		||||
	void *desc;		/* descriptor ring virtual address */
 | 
			
		||||
	dma_addr_t dma;		/* descriptor ring physical address */
 | 
			
		||||
	u16 size;		/* descriptor ring length in bytes */
 | 
			
		||||
	u16 count;		/* number of descriptors in the ring */
 | 
			
		||||
	u16 next_to_use; 	/* this is protectd by adapter->tx_lock */
 | 
			
		||||
	atomic_t next_to_clean;
 | 
			
		||||
	struct atl1c_buffer *buffer_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* receive free descriptor (rfd) ring */
 | 
			
		||||
struct atl1c_rfd_ring {
 | 
			
		||||
	void *desc;		/* descriptor ring virtual address */
 | 
			
		||||
	dma_addr_t dma;		/* descriptor ring physical address */
 | 
			
		||||
	u16 size;		/* descriptor ring length in bytes */
 | 
			
		||||
	u16 count;		/* number of descriptors in the ring */
 | 
			
		||||
	u16 next_to_use;
 | 
			
		||||
	u16 next_to_clean;
 | 
			
		||||
	struct atl1c_buffer *buffer_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* receive return desciptor (rrd) ring */
 | 
			
		||||
struct atl1c_rrd_ring {
 | 
			
		||||
	void *desc;		/* descriptor ring virtual address */
 | 
			
		||||
	dma_addr_t dma;		/* descriptor ring physical address */
 | 
			
		||||
	u16 size;		/* descriptor ring length in bytes */
 | 
			
		||||
	u16 count;		/* number of descriptors in the ring */
 | 
			
		||||
	u16 next_to_use;
 | 
			
		||||
	u16 next_to_clean;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct atl1c_cmb {
 | 
			
		||||
	void *cmb;
 | 
			
		||||
	dma_addr_t dma;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct atl1c_smb {
 | 
			
		||||
	void *smb;
 | 
			
		||||
	dma_addr_t dma;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* board specific private data structure */
 | 
			
		||||
struct atl1c_adapter {
 | 
			
		||||
	struct net_device   *netdev;
 | 
			
		||||
	struct pci_dev      *pdev;
 | 
			
		||||
	struct vlan_group   *vlgrp;
 | 
			
		||||
	struct napi_struct  napi;
 | 
			
		||||
	struct atl1c_hw        hw;
 | 
			
		||||
	struct atl1c_hw_stats  hw_stats;
 | 
			
		||||
	struct net_device_stats net_stats;
 | 
			
		||||
	struct mii_if_info  mii;    /* MII interface info */
 | 
			
		||||
	u16 rx_buffer_len;
 | 
			
		||||
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
#define __AT_TESTING        0x0001
 | 
			
		||||
#define __AT_RESETTING      0x0002
 | 
			
		||||
#define __AT_DOWN           0x0003
 | 
			
		||||
	u32 msg_enable;
 | 
			
		||||
 | 
			
		||||
	bool have_msi;
 | 
			
		||||
	u32 wol;
 | 
			
		||||
	u16 link_speed;
 | 
			
		||||
	u16 link_duplex;
 | 
			
		||||
 | 
			
		||||
	spinlock_t mdio_lock;
 | 
			
		||||
	spinlock_t tx_lock;
 | 
			
		||||
	atomic_t irq_sem;
 | 
			
		||||
 | 
			
		||||
	struct work_struct reset_task;
 | 
			
		||||
	struct work_struct link_chg_task;
 | 
			
		||||
	struct timer_list watchdog_timer;
 | 
			
		||||
	struct timer_list phy_config_timer;
 | 
			
		||||
 | 
			
		||||
	/* All Descriptor memory */
 | 
			
		||||
	struct atl1c_ring_header ring_header;
 | 
			
		||||
	struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE];
 | 
			
		||||
	struct atl1c_rfd_ring rfd_ring[AT_MAX_RECEIVE_QUEUE];
 | 
			
		||||
	struct atl1c_rrd_ring rrd_ring[AT_MAX_RECEIVE_QUEUE];
 | 
			
		||||
	struct atl1c_cmb cmb;
 | 
			
		||||
	struct atl1c_smb smb;
 | 
			
		||||
	int num_rx_queues;
 | 
			
		||||
	u32 bd_number;     /* board number;*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define AT_WRITE_REG(a, reg, value) ( \
 | 
			
		||||
		writel((value), ((a)->hw_addr + reg)))
 | 
			
		||||
 | 
			
		||||
#define AT_WRITE_FLUSH(a) (\
 | 
			
		||||
		readl((a)->hw_addr))
 | 
			
		||||
 | 
			
		||||
#define AT_READ_REG(a, reg, pdata) do {					\
 | 
			
		||||
		if (unlikely((a)->hibernate)) {				\
 | 
			
		||||
			readl((a)->hw_addr + reg);			\
 | 
			
		||||
			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
 | 
			
		||||
		} else {						\
 | 
			
		||||
			*(u32 *)pdata = readl((a)->hw_addr + reg);	\
 | 
			
		||||
		}							\
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#define AT_WRITE_REGB(a, reg, value) (\
 | 
			
		||||
		writeb((value), ((a)->hw_addr + reg)))
 | 
			
		||||
 | 
			
		||||
#define AT_READ_REGB(a, reg) (\
 | 
			
		||||
		readb((a)->hw_addr + reg))
 | 
			
		||||
 | 
			
		||||
#define AT_WRITE_REGW(a, reg, value) (\
 | 
			
		||||
		writew((value), ((a)->hw_addr + reg)))
 | 
			
		||||
 | 
			
		||||
#define AT_READ_REGW(a, reg) (\
 | 
			
		||||
		readw((a)->hw_addr + reg))
 | 
			
		||||
 | 
			
		||||
#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \
 | 
			
		||||
		writel((value), (((a)->hw_addr + reg) + ((offset) << 2))))
 | 
			
		||||
 | 
			
		||||
#define AT_READ_REG_ARRAY(a, reg, offset) ( \
 | 
			
		||||
		readl(((a)->hw_addr + reg) + ((offset) << 2)))
 | 
			
		||||
 | 
			
		||||
extern char atl1c_driver_name[];
 | 
			
		||||
extern char atl1c_driver_version[];
 | 
			
		||||
 | 
			
		||||
extern int atl1c_up(struct atl1c_adapter *adapter);
 | 
			
		||||
extern void atl1c_down(struct atl1c_adapter *adapter);
 | 
			
		||||
extern void atl1c_reinit_locked(struct atl1c_adapter *adapter);
 | 
			
		||||
extern s32 atl1c_reset_hw(struct atl1c_hw *hw);
 | 
			
		||||
extern void atl1c_set_ethtool_ops(struct net_device *netdev);
 | 
			
		||||
#endif /* _ATL1C_H_ */
 | 
			
		||||
							
								
								
									
										317
									
								
								drivers/net/atl1c/atl1c_ethtool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								drivers/net/atl1c/atl1c_ethtool.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,317 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Derived from Intel e1000 driver
 | 
			
		||||
 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
 * Software Foundation; either version 2 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/netdevice.h>
 | 
			
		||||
#include <linux/ethtool.h>
 | 
			
		||||
 | 
			
		||||
#include "atl1c.h"
 | 
			
		||||
 | 
			
		||||
static int atl1c_get_settings(struct net_device *netdev,
 | 
			
		||||
			      struct ethtool_cmd *ecmd)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	struct atl1c_hw *hw = &adapter->hw;
 | 
			
		||||
 | 
			
		||||
	ecmd->supported = (SUPPORTED_10baseT_Half  |
 | 
			
		||||
			   SUPPORTED_10baseT_Full  |
 | 
			
		||||
			   SUPPORTED_100baseT_Half |
 | 
			
		||||
			   SUPPORTED_100baseT_Full |
 | 
			
		||||
			   SUPPORTED_Autoneg       |
 | 
			
		||||
			   SUPPORTED_TP);
 | 
			
		||||
	if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M)
 | 
			
		||||
		ecmd->supported |= SUPPORTED_1000baseT_Full;
 | 
			
		||||
 | 
			
		||||
	ecmd->advertising = ADVERTISED_TP;
 | 
			
		||||
 | 
			
		||||
	ecmd->advertising |= hw->autoneg_advertised;
 | 
			
		||||
 | 
			
		||||
	ecmd->port = PORT_TP;
 | 
			
		||||
	ecmd->phy_address = 0;
 | 
			
		||||
	ecmd->transceiver = XCVR_INTERNAL;
 | 
			
		||||
 | 
			
		||||
	if (adapter->link_speed != SPEED_0) {
 | 
			
		||||
		ecmd->speed = adapter->link_speed;
 | 
			
		||||
		if (adapter->link_duplex == FULL_DUPLEX)
 | 
			
		||||
			ecmd->duplex = DUPLEX_FULL;
 | 
			
		||||
		else
 | 
			
		||||
			ecmd->duplex = DUPLEX_HALF;
 | 
			
		||||
	} else {
 | 
			
		||||
		ecmd->speed = -1;
 | 
			
		||||
		ecmd->duplex = -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ecmd->autoneg = AUTONEG_ENABLE;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_set_settings(struct net_device *netdev,
 | 
			
		||||
			      struct ethtool_cmd *ecmd)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	struct atl1c_hw *hw = &adapter->hw;
 | 
			
		||||
	u16  autoneg_advertised;
 | 
			
		||||
 | 
			
		||||
	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 | 
			
		||||
		msleep(1);
 | 
			
		||||
 | 
			
		||||
	if (ecmd->autoneg == AUTONEG_ENABLE) {
 | 
			
		||||
		autoneg_advertised = ADVERTISED_Autoneg;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (ecmd->speed == SPEED_1000) {
 | 
			
		||||
			if (ecmd->duplex != DUPLEX_FULL) {
 | 
			
		||||
				if (netif_msg_link(adapter))
 | 
			
		||||
					dev_warn(&adapter->pdev->dev,
 | 
			
		||||
						"1000M half is invalid\n");
 | 
			
		||||
				clear_bit(__AT_RESETTING, &adapter->flags);
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			}
 | 
			
		||||
			autoneg_advertised = ADVERTISED_1000baseT_Full;
 | 
			
		||||
		} else if (ecmd->speed == SPEED_100) {
 | 
			
		||||
			if (ecmd->duplex == DUPLEX_FULL)
 | 
			
		||||
				autoneg_advertised = ADVERTISED_100baseT_Full;
 | 
			
		||||
			else
 | 
			
		||||
				autoneg_advertised = ADVERTISED_100baseT_Half;
 | 
			
		||||
		} else {
 | 
			
		||||
			if (ecmd->duplex == DUPLEX_FULL)
 | 
			
		||||
				autoneg_advertised = ADVERTISED_10baseT_Full;
 | 
			
		||||
			else
 | 
			
		||||
				autoneg_advertised = ADVERTISED_10baseT_Half;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (hw->autoneg_advertised != autoneg_advertised) {
 | 
			
		||||
		hw->autoneg_advertised = autoneg_advertised;
 | 
			
		||||
		if (atl1c_restart_autoneg(hw) != 0) {
 | 
			
		||||
			if (netif_msg_link(adapter))
 | 
			
		||||
				dev_warn(&adapter->pdev->dev,
 | 
			
		||||
					"ethtool speed/duplex setting failed\n");
 | 
			
		||||
			clear_bit(__AT_RESETTING, &adapter->flags);
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	clear_bit(__AT_RESETTING, &adapter->flags);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 atl1c_get_tx_csum(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	return (netdev->features & NETIF_F_HW_CSUM) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 atl1c_get_msglevel(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	return adapter->msg_enable;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atl1c_set_msglevel(struct net_device *netdev, u32 data)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	adapter->msg_enable = data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_get_regs_len(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	return AT_REGS_LEN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atl1c_get_regs(struct net_device *netdev,
 | 
			
		||||
			   struct ethtool_regs *regs, void *p)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	struct atl1c_hw *hw = &adapter->hw;
 | 
			
		||||
	u32 *regs_buff = p;
 | 
			
		||||
	u16 phy_data;
 | 
			
		||||
 | 
			
		||||
	memset(p, 0, AT_REGS_LEN);
 | 
			
		||||
 | 
			
		||||
	regs->version = 0;
 | 
			
		||||
	AT_READ_REG(hw, REG_VPD_CAP, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_PM_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL,  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_TWSI_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL,   p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MASTER_CTRL, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MANUAL_TIMER_INIT,    p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_GPHY_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_LINK_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_IDLE_STATUS, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MDIO_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_SERDES_LOCK, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_IPG_IFG, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_STA_ADDR, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_STA_ADDR+4, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_RX_HASH_TABLE, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_RX_HASH_TABLE+4, 	  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_RXQ_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_TXQ_CTRL, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_MTU, 		  p++);
 | 
			
		||||
	AT_READ_REG(hw, REG_WOL_CTRL, 		  p++);
 | 
			
		||||
 | 
			
		||||
	atl1c_read_phy_reg(hw, MII_BMCR, &phy_data);
 | 
			
		||||
	regs_buff[73] =	(u32) phy_data;
 | 
			
		||||
	atl1c_read_phy_reg(hw, MII_BMSR, &phy_data);
 | 
			
		||||
	regs_buff[74] = (u32) phy_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_get_eeprom_len(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
 | 
			
		||||
	if (atl1c_check_eeprom_exist(&adapter->hw))
 | 
			
		||||
		return AT_EEPROM_LEN;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_get_eeprom(struct net_device *netdev,
 | 
			
		||||
		struct ethtool_eeprom *eeprom, u8 *bytes)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	struct atl1c_hw *hw = &adapter->hw;
 | 
			
		||||
	u32 *eeprom_buff;
 | 
			
		||||
	int first_dword, last_dword;
 | 
			
		||||
	int ret_val = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (eeprom->len == 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (!atl1c_check_eeprom_exist(hw)) /* not exist */
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	eeprom->magic = adapter->pdev->vendor |
 | 
			
		||||
			(adapter->pdev->device << 16);
 | 
			
		||||
 | 
			
		||||
	first_dword = eeprom->offset >> 2;
 | 
			
		||||
	last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
 | 
			
		||||
 | 
			
		||||
	eeprom_buff = kmalloc(sizeof(u32) *
 | 
			
		||||
			(last_dword - first_dword + 1), GFP_KERNEL);
 | 
			
		||||
	if (eeprom_buff == NULL)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	for (i = first_dword; i < last_dword; i++) {
 | 
			
		||||
		if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) {
 | 
			
		||||
			kfree(eeprom_buff);
 | 
			
		||||
			return -EIO;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3),
 | 
			
		||||
			eeprom->len);
 | 
			
		||||
	kfree(eeprom_buff);
 | 
			
		||||
 | 
			
		||||
	return ret_val;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atl1c_get_drvinfo(struct net_device *netdev,
 | 
			
		||||
		struct ethtool_drvinfo *drvinfo)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
 | 
			
		||||
	strncpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
 | 
			
		||||
	strncpy(drvinfo->version, atl1c_driver_version,
 | 
			
		||||
		sizeof(drvinfo->version));
 | 
			
		||||
	strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
 | 
			
		||||
	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
 | 
			
		||||
		sizeof(drvinfo->bus_info));
 | 
			
		||||
	drvinfo->n_stats = 0;
 | 
			
		||||
	drvinfo->testinfo_len = 0;
 | 
			
		||||
	drvinfo->regdump_len = atl1c_get_regs_len(netdev);
 | 
			
		||||
	drvinfo->eedump_len = atl1c_get_eeprom_len(netdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atl1c_get_wol(struct net_device *netdev,
 | 
			
		||||
			  struct ethtool_wolinfo *wol)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
 | 
			
		||||
	wol->supported = WAKE_MAGIC | WAKE_PHY;
 | 
			
		||||
	wol->wolopts = 0;
 | 
			
		||||
 | 
			
		||||
	if (adapter->wol & AT_WUFC_EX)
 | 
			
		||||
		wol->wolopts |= WAKE_UCAST;
 | 
			
		||||
	if (adapter->wol & AT_WUFC_MC)
 | 
			
		||||
		wol->wolopts |= WAKE_MCAST;
 | 
			
		||||
	if (adapter->wol & AT_WUFC_BC)
 | 
			
		||||
		wol->wolopts |= WAKE_BCAST;
 | 
			
		||||
	if (adapter->wol & AT_WUFC_MAG)
 | 
			
		||||
		wol->wolopts |= WAKE_MAGIC;
 | 
			
		||||
	if (adapter->wol & AT_WUFC_LNKC)
 | 
			
		||||
		wol->wolopts |= WAKE_PHY;
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
 | 
			
		||||
	if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE |
 | 
			
		||||
			    WAKE_MCAST | WAKE_BCAST | WAKE_MCAST))
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
	/* these settings will always override what we currently have */
 | 
			
		||||
	adapter->wol = 0;
 | 
			
		||||
 | 
			
		||||
	if (wol->wolopts & WAKE_MAGIC)
 | 
			
		||||
		adapter->wol |= AT_WUFC_MAG;
 | 
			
		||||
	if (wol->wolopts & WAKE_PHY)
 | 
			
		||||
		adapter->wol |= AT_WUFC_LNKC;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int atl1c_nway_reset(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = netdev_priv(netdev);
 | 
			
		||||
	if (netif_running(netdev))
 | 
			
		||||
		atl1c_reinit_locked(adapter);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct ethtool_ops atl1c_ethtool_ops = {
 | 
			
		||||
	.get_settings           = atl1c_get_settings,
 | 
			
		||||
	.set_settings           = atl1c_set_settings,
 | 
			
		||||
	.get_drvinfo            = atl1c_get_drvinfo,
 | 
			
		||||
	.get_regs_len           = atl1c_get_regs_len,
 | 
			
		||||
	.get_regs               = atl1c_get_regs,
 | 
			
		||||
	.get_wol                = atl1c_get_wol,
 | 
			
		||||
	.set_wol                = atl1c_set_wol,
 | 
			
		||||
	.get_msglevel           = atl1c_get_msglevel,
 | 
			
		||||
	.set_msglevel           = atl1c_set_msglevel,
 | 
			
		||||
	.nway_reset             = atl1c_nway_reset,
 | 
			
		||||
	.get_link               = ethtool_op_get_link,
 | 
			
		||||
	.get_eeprom_len         = atl1c_get_eeprom_len,
 | 
			
		||||
	.get_eeprom             = atl1c_get_eeprom,
 | 
			
		||||
	.get_tx_csum            = atl1c_get_tx_csum,
 | 
			
		||||
	.get_sg                 = ethtool_op_get_sg,
 | 
			
		||||
	.set_sg                 = ethtool_op_set_sg,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void atl1c_set_ethtool_ops(struct net_device *netdev)
 | 
			
		||||
{
 | 
			
		||||
	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										527
									
								
								drivers/net/atl1c/atl1c_hw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								drivers/net/atl1c/atl1c_hw.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,527 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2007 Atheros Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Derived from Intel e1000 driver
 | 
			
		||||
 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
 * Software Foundation; either version 2 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/pci.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
#include <linux/mii.h>
 | 
			
		||||
#include <linux/crc32.h>
 | 
			
		||||
 | 
			
		||||
#include "atl1c.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * check_eeprom_exist
 | 
			
		||||
 * return 1 if eeprom exist
 | 
			
		||||
 */
 | 
			
		||||
int atl1c_check_eeprom_exist(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	u32 data;
 | 
			
		||||
 | 
			
		||||
	AT_READ_REG(hw, REG_TWSI_DEBUG, &data);
 | 
			
		||||
	if (data & TWSI_DEBUG_DEV_EXIST)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void atl1c_hw_set_mac_addr(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	u32 value;
 | 
			
		||||
	/*
 | 
			
		||||
	 * 00-0B-6A-F6-00-DC
 | 
			
		||||
	 * 0:  6AF600DC 1: 000B
 | 
			
		||||
	 * low dword
 | 
			
		||||
	 */
 | 
			
		||||
	value = (((u32)hw->mac_addr[2]) << 24) |
 | 
			
		||||
		(((u32)hw->mac_addr[3]) << 16) |
 | 
			
		||||
		(((u32)hw->mac_addr[4]) << 8)  |
 | 
			
		||||
		(((u32)hw->mac_addr[5])) ;
 | 
			
		||||
	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
 | 
			
		||||
	/* hight dword */
 | 
			
		||||
	value = (((u32)hw->mac_addr[0]) << 8) |
 | 
			
		||||
		(((u32)hw->mac_addr[1])) ;
 | 
			
		||||
	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * atl1c_get_permanent_address
 | 
			
		||||
 * return 0 if get valid mac address,
 | 
			
		||||
 */
 | 
			
		||||
static int atl1c_get_permanent_address(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	u32 addr[2];
 | 
			
		||||
	u32 i;
 | 
			
		||||
	u32 otp_ctrl_data;
 | 
			
		||||
	u32 twsi_ctrl_data;
 | 
			
		||||
	u8  eth_addr[ETH_ALEN];
 | 
			
		||||
 | 
			
		||||
	/* init */
 | 
			
		||||
	addr[0] = addr[1] = 0;
 | 
			
		||||
	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
 | 
			
		||||
	if (atl1c_check_eeprom_exist(hw)) {
 | 
			
		||||
		/* Enable OTP CLK */
 | 
			
		||||
		if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) {
 | 
			
		||||
			otp_ctrl_data |= OTP_CTRL_CLK_EN;
 | 
			
		||||
			AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
 | 
			
		||||
			AT_WRITE_FLUSH(hw);
 | 
			
		||||
			msleep(1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
 | 
			
		||||
		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
 | 
			
		||||
		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
 | 
			
		||||
		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
 | 
			
		||||
			msleep(10);
 | 
			
		||||
			AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data);
 | 
			
		||||
			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		if (i >= AT_TWSI_EEPROM_TIMEOUT)
 | 
			
		||||
			return -1;
 | 
			
		||||
	}
 | 
			
		||||
	/* Disable OTP_CLK */
 | 
			
		||||
	if (otp_ctrl_data & OTP_CTRL_CLK_EN) {
 | 
			
		||||
		otp_ctrl_data &= ~OTP_CTRL_CLK_EN;
 | 
			
		||||
		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
 | 
			
		||||
		AT_WRITE_FLUSH(hw);
 | 
			
		||||
		msleep(1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* maybe MAC-address is from BIOS */
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]);
 | 
			
		||||
	AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]);
 | 
			
		||||
	*(u32 *) ð_addr[2] = swab32(addr[0]);
 | 
			
		||||
	*(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]);
 | 
			
		||||
 | 
			
		||||
	if (is_valid_ether_addr(eth_addr)) {
 | 
			
		||||
		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int ret = false;
 | 
			
		||||
	u32 otp_ctrl_data;
 | 
			
		||||
	u32 control;
 | 
			
		||||
	u32 data;
 | 
			
		||||
 | 
			
		||||
	if (offset & 3)
 | 
			
		||||
		return ret; /* address do not align */
 | 
			
		||||
 | 
			
		||||
	AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data);
 | 
			
		||||
	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
 | 
			
		||||
		AT_WRITE_REG(hw, REG_OTP_CTRL,
 | 
			
		||||
				(otp_ctrl_data | OTP_CTRL_CLK_EN));
 | 
			
		||||
 | 
			
		||||
	AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0);
 | 
			
		||||
	control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT;
 | 
			
		||||
	AT_WRITE_REG(hw, REG_EEPROM_CTRL, control);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 10; i++) {
 | 
			
		||||
		udelay(100);
 | 
			
		||||
		AT_READ_REG(hw, REG_EEPROM_CTRL, &control);
 | 
			
		||||
		if (control & EEPROM_CTRL_RW)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (control & EEPROM_CTRL_RW) {
 | 
			
		||||
		AT_READ_REG(hw, REG_EEPROM_CTRL, &data);
 | 
			
		||||
		AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value);
 | 
			
		||||
		data = data & 0xFFFF;
 | 
			
		||||
		*p_value = swab32((data << 16) | (*p_value >> 16));
 | 
			
		||||
		ret = true;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(otp_ctrl_data & OTP_CTRL_CLK_EN))
 | 
			
		||||
		AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * Reads the adapter's MAC address from the EEPROM
 | 
			
		||||
 *
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 */
 | 
			
		||||
int atl1c_read_mac_addr(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	int err = 0;
 | 
			
		||||
 | 
			
		||||
	err = atl1c_get_permanent_address(hw);
 | 
			
		||||
	if (err)
 | 
			
		||||
		random_ether_addr(hw->perm_mac_addr);
 | 
			
		||||
 | 
			
		||||
	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * atl1c_hash_mc_addr
 | 
			
		||||
 *  purpose
 | 
			
		||||
 *      set hash value for a multicast address
 | 
			
		||||
 *      hash calcu processing :
 | 
			
		||||
 *          1. calcu 32bit CRC for multicast address
 | 
			
		||||
 *          2. reverse crc with MSB to LSB
 | 
			
		||||
 */
 | 
			
		||||
u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr)
 | 
			
		||||
{
 | 
			
		||||
	u32 crc32;
 | 
			
		||||
	u32 value = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	crc32 = ether_crc_le(6, mc_addr);
 | 
			
		||||
	for (i = 0; i < 32; i++)
 | 
			
		||||
		value |= (((crc32 >> i) & 1) << (31 - i));
 | 
			
		||||
 | 
			
		||||
	return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Sets the bit in the multicast table corresponding to the hash value.
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 * hash_value - Multicast address hash value
 | 
			
		||||
 */
 | 
			
		||||
void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value)
 | 
			
		||||
{
 | 
			
		||||
	u32 hash_bit, hash_reg;
 | 
			
		||||
	u32 mta;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The HASH Table  is a register array of 2 32-bit registers.
 | 
			
		||||
	 * It is treated like an array of 64 bits.  We want to set
 | 
			
		||||
	 * bit BitArray[hash_value]. So we figure out what register
 | 
			
		||||
	 * the bit is in, read it, OR in the new bit, then write
 | 
			
		||||
	 * back the new value.  The register is determined by the
 | 
			
		||||
	 * upper bit of the hash value and the bit within that
 | 
			
		||||
	 * register are determined by the lower 5 bits of the value.
 | 
			
		||||
	 */
 | 
			
		||||
	hash_reg = (hash_value >> 31) & 0x1;
 | 
			
		||||
	hash_bit = (hash_value >> 26) & 0x1F;
 | 
			
		||||
 | 
			
		||||
	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
 | 
			
		||||
 | 
			
		||||
	mta |= (1 << hash_bit);
 | 
			
		||||
 | 
			
		||||
	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Reads the value from a PHY register
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 * reg_addr - address of the PHY register to read
 | 
			
		||||
 */
 | 
			
		||||
int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data)
 | 
			
		||||
{
 | 
			
		||||
	u32 val;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
 | 
			
		||||
		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
 | 
			
		||||
		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
 | 
			
		||||
 | 
			
		||||
	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
 | 
			
		||||
		udelay(2);
 | 
			
		||||
		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
 | 
			
		||||
		if (!(val & (MDIO_START | MDIO_BUSY)))
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(val & (MDIO_START | MDIO_BUSY))) {
 | 
			
		||||
		*phy_data = (u16)val;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Writes a value to a PHY register
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 * reg_addr - address of the PHY register to write
 | 
			
		||||
 * data - data to write to the PHY
 | 
			
		||||
 */
 | 
			
		||||
int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	u32 val;
 | 
			
		||||
 | 
			
		||||
	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT   |
 | 
			
		||||
	       (reg_addr & MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
 | 
			
		||||
	       MDIO_SUP_PREAMBLE | MDIO_START |
 | 
			
		||||
	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
 | 
			
		||||
 | 
			
		||||
	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
 | 
			
		||||
		udelay(2);
 | 
			
		||||
		AT_READ_REG(hw, REG_MDIO_CTRL, &val);
 | 
			
		||||
		if (!(val & (MDIO_START | MDIO_BUSY)))
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(val & (MDIO_START | MDIO_BUSY)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Configures PHY autoneg and flow control advertisement settings
 | 
			
		||||
 *
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 */
 | 
			
		||||
static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
 | 
			
		||||
	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
 | 
			
		||||
				~GIGA_CR_1000T_SPEED_MASK;
 | 
			
		||||
 | 
			
		||||
	if (hw->autoneg_advertised & ADVERTISED_10baseT_Half)
 | 
			
		||||
		mii_adv_data |= ADVERTISE_10HALF;
 | 
			
		||||
	if (hw->autoneg_advertised & ADVERTISED_10baseT_Full)
 | 
			
		||||
		mii_adv_data |= ADVERTISE_10FULL;
 | 
			
		||||
	if (hw->autoneg_advertised & ADVERTISED_100baseT_Half)
 | 
			
		||||
		mii_adv_data |= ADVERTISE_100HALF;
 | 
			
		||||
	if (hw->autoneg_advertised & ADVERTISED_100baseT_Full)
 | 
			
		||||
		mii_adv_data |= ADVERTISE_100FULL;
 | 
			
		||||
 | 
			
		||||
	if (hw->autoneg_advertised & ADVERTISED_Autoneg)
 | 
			
		||||
		mii_adv_data |= ADVERTISE_10HALF  | ADVERTISE_10FULL |
 | 
			
		||||
				ADVERTISE_100HALF | ADVERTISE_100FULL;
 | 
			
		||||
 | 
			
		||||
	if (hw->ctrl_flags & ATL1C_LINK_CAP_1000M) {
 | 
			
		||||
		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half)
 | 
			
		||||
			mii_giga_ctrl_data |= ADVERTISE_1000HALF;
 | 
			
		||||
		if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full)
 | 
			
		||||
			mii_giga_ctrl_data |= ADVERTISE_1000FULL;
 | 
			
		||||
		if (hw->autoneg_advertised & ADVERTISED_Autoneg)
 | 
			
		||||
			mii_giga_ctrl_data |= ADVERTISE_1000HALF |
 | 
			
		||||
					ADVERTISE_1000FULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
 | 
			
		||||
	    atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void atl1c_phy_disable(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
 | 
			
		||||
			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void atl1c_phy_magic_data(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	u16 data;
 | 
			
		||||
 | 
			
		||||
	data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
 | 
			
		||||
		((1 & ANA_INTERVAL_SEL_TIMER_MASK) <<
 | 
			
		||||
		ANA_INTERVAL_SEL_TIMER_SHIFT);
 | 
			
		||||
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_18);
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
	data = (2 & ANA_SERDES_CDR_BW_MASK) | ANA_MS_PAD_DBG |
 | 
			
		||||
		ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP | ANA_SERDES_EN_PLL |
 | 
			
		||||
		ANA_SERDES_EN_LCKDT;
 | 
			
		||||
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_5);
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
	data = (44 & ANA_LONG_CABLE_TH_100_MASK) |
 | 
			
		||||
		((33 & ANA_SHORT_CABLE_TH_100_MASK) <<
 | 
			
		||||
		ANA_SHORT_CABLE_TH_100_SHIFT) | ANA_BP_BAD_LINK_ACCUM |
 | 
			
		||||
		ANA_BP_SMALL_BW;
 | 
			
		||||
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_54);
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
	data = (11 & ANA_IECHO_ADJ_MASK) | ((11 & ANA_IECHO_ADJ_MASK) <<
 | 
			
		||||
		ANA_IECHO_ADJ_2_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
 | 
			
		||||
		ANA_IECHO_ADJ_1_SHIFT) | ((8 & ANA_IECHO_ADJ_MASK) <<
 | 
			
		||||
		ANA_IECHO_ADJ_0_SHIFT);
 | 
			
		||||
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_4);
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
	data = ANA_RESTART_CAL | ((7 & ANA_MANUL_SWICH_ON_MASK) <<
 | 
			
		||||
		ANA_MANUL_SWICH_ON_SHIFT) | ANA_MAN_ENABLE |
 | 
			
		||||
		ANA_SEL_HSP | ANA_EN_HB | ANA_OEN_125M;
 | 
			
		||||
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_0);
 | 
			
		||||
	atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
	if (hw->ctrl_flags & ATL1C_HIB_DISABLE) {
 | 
			
		||||
		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_41);
 | 
			
		||||
		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
 | 
			
		||||
			return;
 | 
			
		||||
		data &= ~ANA_TOP_PS_EN;
 | 
			
		||||
		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
 | 
			
		||||
		atl1c_write_phy_reg(hw, MII_DBG_ADDR, MII_ANA_CTRL_11);
 | 
			
		||||
		if (atl1c_read_phy_reg(hw, MII_DBG_DATA, &data) != 0)
 | 
			
		||||
			return;
 | 
			
		||||
		data &= ~ANA_PS_HIB_EN;
 | 
			
		||||
		atl1c_write_phy_reg(hw, MII_DBG_DATA, data);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int atl1c_phy_reset(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = hw->adapter;
 | 
			
		||||
	struct pci_dev *pdev = adapter->pdev;
 | 
			
		||||
	u32 phy_ctrl_data = GPHY_CTRL_DEFAULT;
 | 
			
		||||
	u32 mii_ier_data = IER_LINK_UP | IER_LINK_DOWN;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if (hw->ctrl_flags & ATL1C_HIB_DISABLE)
 | 
			
		||||
		phy_ctrl_data &= ~GPHY_CTRL_HIB_EN;
 | 
			
		||||
 | 
			
		||||
	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
 | 
			
		||||
	AT_WRITE_FLUSH(hw);
 | 
			
		||||
	msleep(40);
 | 
			
		||||
	phy_ctrl_data |= GPHY_CTRL_EXT_RESET;
 | 
			
		||||
	AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data);
 | 
			
		||||
	AT_WRITE_FLUSH(hw);
 | 
			
		||||
	msleep(10);
 | 
			
		||||
 | 
			
		||||
	/*Enable PHY LinkChange Interrupt */
 | 
			
		||||
	err = atl1c_write_phy_reg(hw, MII_IER, mii_ier_data);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		if (netif_msg_hw(adapter))
 | 
			
		||||
			dev_err(&pdev->dev,
 | 
			
		||||
				"Error enable PHY linkChange Interrupt\n");
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION))
 | 
			
		||||
		atl1c_phy_magic_data(hw);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int atl1c_phy_init(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	struct atl1c_adapter *adapter = (struct atl1c_adapter *)hw->adapter;
 | 
			
		||||
	struct pci_dev *pdev = adapter->pdev;
 | 
			
		||||
	int ret_val;
 | 
			
		||||
	u16 mii_bmcr_data = BMCR_RESET;
 | 
			
		||||
	u16 phy_id1, phy_id2;
 | 
			
		||||
 | 
			
		||||
	if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &phy_id1) != 0) ||
 | 
			
		||||
		(atl1c_read_phy_reg(hw, MII_PHYSID2, &phy_id2) != 0)) {
 | 
			
		||||
			if (netif_msg_link(adapter))
 | 
			
		||||
				dev_err(&pdev->dev, "Error get phy ID\n");
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	switch (hw->media_type) {
 | 
			
		||||
	case MEDIA_TYPE_AUTO_SENSOR:
 | 
			
		||||
		ret_val = atl1c_phy_setup_adv(hw);
 | 
			
		||||
		if (ret_val) {
 | 
			
		||||
			if (netif_msg_link(adapter))
 | 
			
		||||
				dev_err(&pdev->dev,
 | 
			
		||||
					"Error Setting up Auto-Negotiation\n");
 | 
			
		||||
			return ret_val;
 | 
			
		||||
		}
 | 
			
		||||
		mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
 | 
			
		||||
		break;
 | 
			
		||||
	case MEDIA_TYPE_100M_FULL:
 | 
			
		||||
		mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
 | 
			
		||||
		break;
 | 
			
		||||
	case MEDIA_TYPE_100M_HALF:
 | 
			
		||||
		mii_bmcr_data |= BMCR_SPEED_100;
 | 
			
		||||
		break;
 | 
			
		||||
	case MEDIA_TYPE_10M_FULL:
 | 
			
		||||
		mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
 | 
			
		||||
		break;
 | 
			
		||||
	case MEDIA_TYPE_10M_HALF:
 | 
			
		||||
		mii_bmcr_data |= BMCR_SPEED_10;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		if (netif_msg_link(adapter))
 | 
			
		||||
			dev_err(&pdev->dev, "Wrong Media type %d\n",
 | 
			
		||||
				hw->media_type);
 | 
			
		||||
		return -1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 | 
			
		||||
	if (ret_val)
 | 
			
		||||
		return ret_val;
 | 
			
		||||
	hw->phy_configured = true;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Detects the current speed and duplex settings of the hardware.
 | 
			
		||||
 *
 | 
			
		||||
 * hw - Struct containing variables accessed by shared code
 | 
			
		||||
 * speed - Speed of the connection
 | 
			
		||||
 * duplex - Duplex setting of the connection
 | 
			
		||||
 */
 | 
			
		||||
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	u16 phy_data;
 | 
			
		||||
 | 
			
		||||
	/* Read   PHY Specific Status Register (17) */
 | 
			
		||||
	err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED))
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	switch (phy_data & GIGA_PSSR_SPEED) {
 | 
			
		||||
	case GIGA_PSSR_1000MBS:
 | 
			
		||||
		*speed = SPEED_1000;
 | 
			
		||||
		break;
 | 
			
		||||
	case GIGA_PSSR_100MBS:
 | 
			
		||||
		*speed = SPEED_100;
 | 
			
		||||
		break;
 | 
			
		||||
	case  GIGA_PSSR_10MBS:
 | 
			
		||||
		*speed = SPEED_10;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		return -1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (phy_data & GIGA_PSSR_DPLX)
 | 
			
		||||
		*duplex = FULL_DUPLEX;
 | 
			
		||||
	else
 | 
			
		||||
		*duplex = HALF_DUPLEX;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int atl1c_restart_autoneg(struct atl1c_hw *hw)
 | 
			
		||||
{
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	u16 mii_bmcr_data = BMCR_RESET;
 | 
			
		||||
 | 
			
		||||
	err = atl1c_phy_setup_adv(hw);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
 | 
			
		||||
 | 
			
		||||
	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										859
									
								
								drivers/net/atl1c/atl1c_hw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										859
									
								
								drivers/net/atl1c/atl1c_hw.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,859 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Derived from Intel e1000 driver
 | 
			
		||||
 * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
 * Software Foundation; either version 2 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef _ATL1C_HW_H_
 | 
			
		||||
#define _ATL1C_HW_H_
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/mii.h>
 | 
			
		||||
 | 
			
		||||
struct atl1c_adapter;
 | 
			
		||||
struct atl1c_hw;
 | 
			
		||||
 | 
			
		||||
/* function prototype */
 | 
			
		||||
void atl1c_phy_disable(struct atl1c_hw *hw);
 | 
			
		||||
void atl1c_hw_set_mac_addr(struct atl1c_hw *hw);
 | 
			
		||||
int atl1c_phy_reset(struct atl1c_hw *hw);
 | 
			
		||||
int atl1c_read_mac_addr(struct atl1c_hw *hw);
 | 
			
		||||
int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex);
 | 
			
		||||
u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr);
 | 
			
		||||
void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value);
 | 
			
		||||
int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data);
 | 
			
		||||
int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data);
 | 
			
		||||
bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value);
 | 
			
		||||
int atl1c_phy_init(struct atl1c_hw *hw);
 | 
			
		||||
int atl1c_check_eeprom_exist(struct atl1c_hw *hw);
 | 
			
		||||
int atl1c_restart_autoneg(struct atl1c_hw *hw);
 | 
			
		||||
 | 
			
		||||
/* register definition */
 | 
			
		||||
#define REG_DEVICE_CAP              	0x5C
 | 
			
		||||
#define DEVICE_CAP_MAX_PAYLOAD_MASK     0x7
 | 
			
		||||
#define DEVICE_CAP_MAX_PAYLOAD_SHIFT    0
 | 
			
		||||
 | 
			
		||||
#define REG_DEVICE_CTRL			0x60
 | 
			
		||||
#define DEVICE_CTRL_MAX_PAYLOAD_MASK    0x7
 | 
			
		||||
#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT   5
 | 
			
		||||
#define DEVICE_CTRL_MAX_RREQ_SZ_MASK    0x7
 | 
			
		||||
#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT   12
 | 
			
		||||
 | 
			
		||||
#define REG_LINK_CTRL			0x68
 | 
			
		||||
#define LINK_CTRL_L0S_EN		0x01
 | 
			
		||||
#define LINK_CTRL_L1_EN			0x02
 | 
			
		||||
 | 
			
		||||
#define REG_VPD_CAP			0x6C
 | 
			
		||||
#define VPD_CAP_ID_MASK                 0xff
 | 
			
		||||
#define VPD_CAP_ID_SHIFT                0
 | 
			
		||||
#define VPD_CAP_NEXT_PTR_MASK           0xFF
 | 
			
		||||
#define VPD_CAP_NEXT_PTR_SHIFT          8
 | 
			
		||||
#define VPD_CAP_VPD_ADDR_MASK           0x7FFF
 | 
			
		||||
#define VPD_CAP_VPD_ADDR_SHIFT          16
 | 
			
		||||
#define VPD_CAP_VPD_FLAG                0x80000000
 | 
			
		||||
 | 
			
		||||
#define REG_VPD_DATA                	0x70
 | 
			
		||||
 | 
			
		||||
#define REG_PCIE_UC_SEVERITY		0x10C
 | 
			
		||||
#define PCIE_UC_SERVRITY_TRN		0x00000001
 | 
			
		||||
#define PCIE_UC_SERVRITY_DLP		0x00000010
 | 
			
		||||
#define PCIE_UC_SERVRITY_PSN_TLP	0x00001000
 | 
			
		||||
#define PCIE_UC_SERVRITY_FCP		0x00002000
 | 
			
		||||
#define PCIE_UC_SERVRITY_CPL_TO		0x00004000
 | 
			
		||||
#define PCIE_UC_SERVRITY_CA		0x00008000
 | 
			
		||||
#define PCIE_UC_SERVRITY_UC		0x00010000
 | 
			
		||||
#define PCIE_UC_SERVRITY_ROV		0x00020000
 | 
			
		||||
#define PCIE_UC_SERVRITY_MLFP		0x00040000
 | 
			
		||||
#define PCIE_UC_SERVRITY_ECRC		0x00080000
 | 
			
		||||
#define PCIE_UC_SERVRITY_UR		0x00100000
 | 
			
		||||
 | 
			
		||||
#define REG_DEV_SERIALNUM_CTRL		0x200
 | 
			
		||||
#define REG_DEV_MAC_SEL_MASK		0x0 /* 0:EUI; 1:MAC */
 | 
			
		||||
#define REG_DEV_MAC_SEL_SHIFT		0
 | 
			
		||||
#define REG_DEV_SERIAL_NUM_EN_MASK	0x1
 | 
			
		||||
#define REG_DEV_SERIAL_NUM_EN_SHIFT	1
 | 
			
		||||
 | 
			
		||||
#define REG_TWSI_CTRL               	0x218
 | 
			
		||||
#define TWSI_CTRL_LD_OFFSET_MASK        0xFF
 | 
			
		||||
#define TWSI_CTRL_LD_OFFSET_SHIFT       0
 | 
			
		||||
#define TWSI_CTRL_LD_SLV_ADDR_MASK      0x7
 | 
			
		||||
#define TWSI_CTRL_LD_SLV_ADDR_SHIFT     8
 | 
			
		||||
#define TWSI_CTRL_SW_LDSTART            0x800
 | 
			
		||||
#define TWSI_CTRL_HW_LDSTART            0x1000
 | 
			
		||||
#define TWSI_CTRL_SMB_SLV_ADDR_MASK     0x7F
 | 
			
		||||
#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT    15
 | 
			
		||||
#define TWSI_CTRL_LD_EXIST              0x400000
 | 
			
		||||
#define TWSI_CTRL_READ_FREQ_SEL_MASK    0x3
 | 
			
		||||
#define TWSI_CTRL_READ_FREQ_SEL_SHIFT   23
 | 
			
		||||
#define TWSI_CTRL_FREQ_SEL_100K         0
 | 
			
		||||
#define TWSI_CTRL_FREQ_SEL_200K         1
 | 
			
		||||
#define TWSI_CTRL_FREQ_SEL_300K         2
 | 
			
		||||
#define TWSI_CTRL_FREQ_SEL_400K         3
 | 
			
		||||
#define TWSI_CTRL_SMB_SLV_ADDR
 | 
			
		||||
#define TWSI_CTRL_WRITE_FREQ_SEL_MASK   0x3
 | 
			
		||||
#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT  24
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define REG_PCIE_DEV_MISC_CTRL      	0x21C
 | 
			
		||||
#define PCIE_DEV_MISC_EXT_PIPE     	0x2
 | 
			
		||||
#define PCIE_DEV_MISC_RETRY_BUFDIS 	0x1
 | 
			
		||||
#define PCIE_DEV_MISC_SPIROM_EXIST 	0x4
 | 
			
		||||
#define PCIE_DEV_MISC_SERDES_ENDIAN    	0x8
 | 
			
		||||
#define PCIE_DEV_MISC_SERDES_SEL_DIN   	0x10
 | 
			
		||||
 | 
			
		||||
#define REG_PCIE_PHYMISC	    	0x1000
 | 
			
		||||
#define PCIE_PHYMISC_FORCE_RCV_DET	0x4
 | 
			
		||||
 | 
			
		||||
#define REG_TWSI_DEBUG			0x1108
 | 
			
		||||
#define TWSI_DEBUG_DEV_EXIST		0x20000000
 | 
			
		||||
 | 
			
		||||
#define REG_EEPROM_CTRL			0x12C0
 | 
			
		||||
#define EEPROM_CTRL_DATA_HI_MASK	0xFFFF
 | 
			
		||||
#define EEPROM_CTRL_DATA_HI_SHIFT	0
 | 
			
		||||
#define EEPROM_CTRL_ADDR_MASK		0x3FF
 | 
			
		||||
#define EEPROM_CTRL_ADDR_SHIFT		16
 | 
			
		||||
#define EEPROM_CTRL_ACK			0x40000000
 | 
			
		||||
#define EEPROM_CTRL_RW			0x80000000
 | 
			
		||||
 | 
			
		||||
#define REG_EEPROM_DATA_LO		0x12C4
 | 
			
		||||
 | 
			
		||||
#define REG_OTP_CTRL			0x12F0
 | 
			
		||||
#define OTP_CTRL_CLK_EN			0x0002
 | 
			
		||||
 | 
			
		||||
#define REG_PM_CTRL			0x12F8
 | 
			
		||||
#define PM_CTRL_SDES_EN			0x00000001
 | 
			
		||||
#define PM_CTRL_RBER_EN			0x00000002
 | 
			
		||||
#define PM_CTRL_CLK_REQ_EN		0x00000004
 | 
			
		||||
#define PM_CTRL_ASPM_L1_EN		0x00000008
 | 
			
		||||
#define PM_CTRL_SERDES_L1_EN		0x00000010
 | 
			
		||||
#define PM_CTRL_SERDES_PLL_L1_EN	0x00000020
 | 
			
		||||
#define PM_CTRL_SERDES_PD_EX_L1		0x00000040
 | 
			
		||||
#define PM_CTRL_SERDES_BUDS_RX_L1_EN	0x00000080
 | 
			
		||||
#define PM_CTRL_L0S_ENTRY_TIMER_MASK	0xF
 | 
			
		||||
#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT	8
 | 
			
		||||
#define PM_CTRL_ASPM_L0S_EN		0x00001000
 | 
			
		||||
#define PM_CTRL_CLK_SWH_L1		0x00002000
 | 
			
		||||
#define PM_CTRL_CLK_PWM_VER1_1		0x00004000
 | 
			
		||||
#define PM_CTRL_PCIE_RECV		0x00008000
 | 
			
		||||
#define PM_CTRL_L1_ENTRY_TIMER_MASK	0xF
 | 
			
		||||
#define PM_CTRL_L1_ENTRY_TIMER_SHIFT	16
 | 
			
		||||
#define PM_CTRL_PM_REQ_TIMER_MASK	0xF
 | 
			
		||||
#define PM_CTRL_PM_REQ_TIMER_SHIFT	20
 | 
			
		||||
#define PM_CTRL_LCKDET_TIMER_MASK	0x3F
 | 
			
		||||
#define PM_CTRL_LCKDET_TIMER_SHIFT	24
 | 
			
		||||
#define PM_CTRL_MAC_ASPM_CHK		0x40000000
 | 
			
		||||
#define PM_CTRL_HOTRST			0x80000000
 | 
			
		||||
 | 
			
		||||
/* Selene Master Control Register */
 | 
			
		||||
#define REG_MASTER_CTRL			0x1400
 | 
			
		||||
#define MASTER_CTRL_SOFT_RST            0x1
 | 
			
		||||
#define MASTER_CTRL_TEST_MODE_MASK	0x3
 | 
			
		||||
#define MASTER_CTRL_TEST_MODE_SHIFT	2
 | 
			
		||||
#define MASTER_CTRL_BERT_START		0x10
 | 
			
		||||
#define MASTER_CTRL_MTIMER_EN           0x100
 | 
			
		||||
#define MASTER_CTRL_MANUAL_INT          0x200
 | 
			
		||||
#define MASTER_CTRL_TX_ITIMER_EN	0x400
 | 
			
		||||
#define MASTER_CTRL_RX_ITIMER_EN	0x800
 | 
			
		||||
#define MASTER_CTRL_CLK_SEL_DIS		0x1000
 | 
			
		||||
#define MASTER_CTRL_CLK_SWH_MODE	0x2000
 | 
			
		||||
#define MASTER_CTRL_INT_RDCLR		0x4000
 | 
			
		||||
#define MASTER_CTRL_REV_NUM_SHIFT	16
 | 
			
		||||
#define MASTER_CTRL_REV_NUM_MASK	0xff
 | 
			
		||||
#define MASTER_CTRL_DEV_ID_SHIFT	24
 | 
			
		||||
#define MASTER_CTRL_DEV_ID_MASK		0x7f
 | 
			
		||||
#define MASTER_CTRL_OTP_SEL		0x80000000
 | 
			
		||||
 | 
			
		||||
/* Timer Initial Value Register */
 | 
			
		||||
#define REG_MANUAL_TIMER_INIT       	0x1404
 | 
			
		||||
 | 
			
		||||
/* IRQ ModeratorTimer Initial Value Register */
 | 
			
		||||
#define REG_IRQ_MODRT_TIMER_INIT     	0x1408
 | 
			
		||||
#define IRQ_MODRT_TIMER_MASK		0xffff
 | 
			
		||||
#define IRQ_MODRT_TX_TIMER_SHIFT    	0
 | 
			
		||||
#define IRQ_MODRT_RX_TIMER_SHIFT	16
 | 
			
		||||
 | 
			
		||||
#define REG_GPHY_CTRL               	0x140C
 | 
			
		||||
#define GPHY_CTRL_EXT_RESET         	0x1
 | 
			
		||||
#define GPHY_CTRL_RTL_MODE		0x2
 | 
			
		||||
#define GPHY_CTRL_LED_MODE		0x4
 | 
			
		||||
#define GPHY_CTRL_ANEG_NOW		0x8
 | 
			
		||||
#define GPHY_CTRL_REV_ANEG		0x10
 | 
			
		||||
#define GPHY_CTRL_GATE_25M_EN       	0x20
 | 
			
		||||
#define GPHY_CTRL_LPW_EXIT          	0x40
 | 
			
		||||
#define GPHY_CTRL_PHY_IDDQ          	0x80
 | 
			
		||||
#define GPHY_CTRL_PHY_IDDQ_DIS      	0x100
 | 
			
		||||
#define GPHY_CTRL_GIGA_DIS		0x200
 | 
			
		||||
#define GPHY_CTRL_HIB_EN            	0x400
 | 
			
		||||
#define GPHY_CTRL_HIB_PULSE         	0x800
 | 
			
		||||
#define GPHY_CTRL_SEL_ANA_RST       	0x1000
 | 
			
		||||
#define GPHY_CTRL_PHY_PLL_ON        	0x2000
 | 
			
		||||
#define GPHY_CTRL_PWDOWN_HW		0x4000
 | 
			
		||||
#define GPHY_CTRL_PHY_PLL_BYPASS	0x8000
 | 
			
		||||
 | 
			
		||||
#define GPHY_CTRL_DEFAULT (		 \
 | 
			
		||||
		GPHY_CTRL_SEL_ANA_RST	|\
 | 
			
		||||
		GPHY_CTRL_HIB_PULSE	|\
 | 
			
		||||
		GPHY_CTRL_HIB_EN)
 | 
			
		||||
 | 
			
		||||
#define GPHY_CTRL_PW_WOL_DIS (		 \
 | 
			
		||||
		GPHY_CTRL_SEL_ANA_RST	|\
 | 
			
		||||
		GPHY_CTRL_HIB_PULSE	|\
 | 
			
		||||
		GPHY_CTRL_HIB_EN	|\
 | 
			
		||||
		GPHY_CTRL_PWDOWN_HW	|\
 | 
			
		||||
		GPHY_CTRL_PHY_IDDQ)
 | 
			
		||||
 | 
			
		||||
/* Block IDLE Status Register */
 | 
			
		||||
#define REG_IDLE_STATUS  		0x1410
 | 
			
		||||
#define IDLE_STATUS_MASK		0x00FF
 | 
			
		||||
#define IDLE_STATUS_RXMAC_NO_IDLE      	0x1
 | 
			
		||||
#define IDLE_STATUS_TXMAC_NO_IDLE      	0x2
 | 
			
		||||
#define IDLE_STATUS_RXQ_NO_IDLE        	0x4
 | 
			
		||||
#define IDLE_STATUS_TXQ_NO_IDLE        	0x8
 | 
			
		||||
#define IDLE_STATUS_DMAR_NO_IDLE       	0x10
 | 
			
		||||
#define IDLE_STATUS_DMAW_NO_IDLE       	0x20
 | 
			
		||||
#define IDLE_STATUS_SMB_NO_IDLE        	0x40
 | 
			
		||||
#define IDLE_STATUS_CMB_NO_IDLE        	0x80
 | 
			
		||||
 | 
			
		||||
/* MDIO Control Register */
 | 
			
		||||
#define REG_MDIO_CTRL           	0x1414
 | 
			
		||||
#define MDIO_DATA_MASK          	0xffff  /* On MDIO write, the 16-bit
 | 
			
		||||
						 * control data to write to PHY
 | 
			
		||||
						 * MII management register */
 | 
			
		||||
#define MDIO_DATA_SHIFT         	0       /* On MDIO read, the 16-bit
 | 
			
		||||
						 * status data that was read
 | 
			
		||||
						 * from the PHY MII management register */
 | 
			
		||||
#define MDIO_REG_ADDR_MASK      	0x1f    /* MDIO register address */
 | 
			
		||||
#define MDIO_REG_ADDR_SHIFT     	16
 | 
			
		||||
#define MDIO_RW                 	0x200000  /* 1: read, 0: write */
 | 
			
		||||
#define MDIO_SUP_PREAMBLE       	0x400000  /* Suppress preamble */
 | 
			
		||||
#define MDIO_START              	0x800000  /* Write 1 to initiate the MDIO
 | 
			
		||||
						   * master. And this bit is self
 | 
			
		||||
						   * cleared after one cycle */
 | 
			
		||||
#define MDIO_CLK_SEL_SHIFT      	24
 | 
			
		||||
#define MDIO_CLK_25_4           	0
 | 
			
		||||
#define MDIO_CLK_25_6           	2
 | 
			
		||||
#define MDIO_CLK_25_8           	3
 | 
			
		||||
#define MDIO_CLK_25_10          	4
 | 
			
		||||
#define MDIO_CLK_25_14          	5
 | 
			
		||||
#define MDIO_CLK_25_20          	6
 | 
			
		||||
#define MDIO_CLK_25_28          	7
 | 
			
		||||
#define MDIO_BUSY               	0x8000000
 | 
			
		||||
#define MDIO_AP_EN              	0x10000000
 | 
			
		||||
#define MDIO_WAIT_TIMES         	10
 | 
			
		||||
 | 
			
		||||
/* MII PHY Status Register */
 | 
			
		||||
#define REG_PHY_STATUS           	0x1418
 | 
			
		||||
#define PHY_GENERAL_STATUS_MASK		0xFFFF
 | 
			
		||||
#define PHY_STATUS_RECV_ENABLE		0x0001
 | 
			
		||||
#define PHY_OE_PWSP_STATUS_MASK		0x07FF
 | 
			
		||||
#define PHY_OE_PWSP_STATUS_SHIFT	16
 | 
			
		||||
#define PHY_STATUS_LPW_STATE		0x80000000
 | 
			
		||||
/* BIST Control and Status Register0 (for the Packet Memory) */
 | 
			
		||||
#define REG_BIST0_CTRL              	0x141c
 | 
			
		||||
#define BIST0_NOW                   	0x1
 | 
			
		||||
#define BIST0_SRAM_FAIL             	0x2 /* 1: The SRAM failure is
 | 
			
		||||
					     * un-repairable  because
 | 
			
		||||
					     * it has address decoder
 | 
			
		||||
					     * failure or more than 1 cell
 | 
			
		||||
					     * stuck-to-x failure */
 | 
			
		||||
#define BIST0_FUSE_FLAG             	0x4
 | 
			
		||||
 | 
			
		||||
/* BIST Control and Status Register1(for the retry buffer of PCI Express) */
 | 
			
		||||
#define REG_BIST1_CTRL			0x1420
 | 
			
		||||
#define BIST1_NOW                   	0x1
 | 
			
		||||
#define BIST1_SRAM_FAIL             	0x2
 | 
			
		||||
#define BIST1_FUSE_FLAG             	0x4
 | 
			
		||||
 | 
			
		||||
/* SerDes Lock Detect Control and Status Register */
 | 
			
		||||
#define REG_SERDES_LOCK            	0x1424
 | 
			
		||||
#define SERDES_LOCK_DETECT          	0x1  /* SerDes lock detected. This signal
 | 
			
		||||
					      * comes from Analog SerDes */
 | 
			
		||||
#define SERDES_LOCK_DETECT_EN       	0x2  /* 1: Enable SerDes Lock detect function */
 | 
			
		||||
 | 
			
		||||
/* MAC Control Register  */
 | 
			
		||||
#define REG_MAC_CTRL         		0x1480
 | 
			
		||||
#define MAC_CTRL_TX_EN			0x1
 | 
			
		||||
#define MAC_CTRL_RX_EN			0x2
 | 
			
		||||
#define MAC_CTRL_TX_FLOW		0x4
 | 
			
		||||
#define MAC_CTRL_RX_FLOW            	0x8
 | 
			
		||||
#define MAC_CTRL_LOOPBACK          	0x10
 | 
			
		||||
#define MAC_CTRL_DUPLX              	0x20
 | 
			
		||||
#define MAC_CTRL_ADD_CRC            	0x40
 | 
			
		||||
#define MAC_CTRL_PAD                	0x80
 | 
			
		||||
#define MAC_CTRL_LENCHK             	0x100
 | 
			
		||||
#define MAC_CTRL_HUGE_EN            	0x200
 | 
			
		||||
#define MAC_CTRL_PRMLEN_SHIFT       	10
 | 
			
		||||
#define MAC_CTRL_PRMLEN_MASK        	0xf
 | 
			
		||||
#define MAC_CTRL_RMV_VLAN           	0x4000
 | 
			
		||||
#define MAC_CTRL_PROMIS_EN          	0x8000
 | 
			
		||||
#define MAC_CTRL_TX_PAUSE           	0x10000
 | 
			
		||||
#define MAC_CTRL_SCNT               	0x20000
 | 
			
		||||
#define MAC_CTRL_SRST_TX            	0x40000
 | 
			
		||||
#define MAC_CTRL_TX_SIMURST         	0x80000
 | 
			
		||||
#define MAC_CTRL_SPEED_SHIFT        	20
 | 
			
		||||
#define MAC_CTRL_SPEED_MASK         	0x3
 | 
			
		||||
#define MAC_CTRL_DBG_TX_BKPRESURE   	0x400000
 | 
			
		||||
#define MAC_CTRL_TX_HUGE            	0x800000
 | 
			
		||||
#define MAC_CTRL_RX_CHKSUM_EN       	0x1000000
 | 
			
		||||
#define MAC_CTRL_MC_ALL_EN          	0x2000000
 | 
			
		||||
#define MAC_CTRL_BC_EN              	0x4000000
 | 
			
		||||
#define MAC_CTRL_DBG                	0x8000000
 | 
			
		||||
#define MAC_CTRL_SINGLE_PAUSE_EN	0x10000000
 | 
			
		||||
 | 
			
		||||
/* MAC IPG/IFG Control Register  */
 | 
			
		||||
#define REG_MAC_IPG_IFG             	0x1484
 | 
			
		||||
#define MAC_IPG_IFG_IPGT_SHIFT      	0 	/* Desired back to back
 | 
			
		||||
						 * inter-packet gap. The
 | 
			
		||||
						 * default is 96-bit time */
 | 
			
		||||
#define MAC_IPG_IFG_IPGT_MASK       	0x7f
 | 
			
		||||
#define MAC_IPG_IFG_MIFG_SHIFT      	8       /* Minimum number of IFG to
 | 
			
		||||
						 * enforce in between RX frames */
 | 
			
		||||
#define MAC_IPG_IFG_MIFG_MASK       	0xff  	/* Frame gap below such IFP is dropped */
 | 
			
		||||
#define MAC_IPG_IFG_IPGR1_SHIFT     	16   	/* 64bit Carrier-Sense window */
 | 
			
		||||
#define MAC_IPG_IFG_IPGR1_MASK      	0x7f
 | 
			
		||||
#define MAC_IPG_IFG_IPGR2_SHIFT     	24    	/* 96-bit IPG window */
 | 
			
		||||
#define MAC_IPG_IFG_IPGR2_MASK      	0x7f
 | 
			
		||||
 | 
			
		||||
/* MAC STATION ADDRESS  */
 | 
			
		||||
#define REG_MAC_STA_ADDR		0x1488
 | 
			
		||||
 | 
			
		||||
/* Hash table for multicast address */
 | 
			
		||||
#define REG_RX_HASH_TABLE		0x1490
 | 
			
		||||
 | 
			
		||||
/* MAC Half-Duplex Control Register */
 | 
			
		||||
#define REG_MAC_HALF_DUPLX_CTRL     	0x1498
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT  0      /* Collision Window */
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_LCOL_MASK   0x3ff
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_RETRY_MASK  0xf
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN  0x10000
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_NO_BACK_C   0x20000
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_NO_BACK_P   0x40000 /* No back-off on backpressure,
 | 
			
		||||
						 * immediately start the
 | 
			
		||||
						 * transmission after back pressure */
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_ABEBE        0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT  20      /* Maximum binary exponential number */
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK   0xf
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24      /* IPG to start JAM for collision based flow control in half-duplex */
 | 
			
		||||
#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK  0xf     /* mode. In unit of 8-bit time */
 | 
			
		||||
 | 
			
		||||
/* Maximum Frame Length Control Register   */
 | 
			
		||||
#define REG_MTU                     	0x149c
 | 
			
		||||
 | 
			
		||||
/* Wake-On-Lan control register */
 | 
			
		||||
#define REG_WOL_CTRL                	0x14a0
 | 
			
		||||
#define WOL_PATTERN_EN              	0x00000001
 | 
			
		||||
#define WOL_PATTERN_PME_EN              0x00000002
 | 
			
		||||
#define WOL_MAGIC_EN                    0x00000004
 | 
			
		||||
#define WOL_MAGIC_PME_EN                0x00000008
 | 
			
		||||
#define WOL_LINK_CHG_EN                 0x00000010
 | 
			
		||||
#define WOL_LINK_CHG_PME_EN             0x00000020
 | 
			
		||||
#define WOL_PATTERN_ST                  0x00000100
 | 
			
		||||
#define WOL_MAGIC_ST                    0x00000200
 | 
			
		||||
#define WOL_LINKCHG_ST                  0x00000400
 | 
			
		||||
#define WOL_CLK_SWITCH_EN               0x00008000
 | 
			
		||||
#define WOL_PT0_EN                      0x00010000
 | 
			
		||||
#define WOL_PT1_EN                      0x00020000
 | 
			
		||||
#define WOL_PT2_EN                      0x00040000
 | 
			
		||||
#define WOL_PT3_EN                      0x00080000
 | 
			
		||||
#define WOL_PT4_EN                      0x00100000
 | 
			
		||||
#define WOL_PT5_EN                      0x00200000
 | 
			
		||||
#define WOL_PT6_EN                      0x00400000
 | 
			
		||||
 | 
			
		||||
/* WOL Length ( 2 DWORD ) */
 | 
			
		||||
#define REG_WOL_PATTERN_LEN         	0x14a4
 | 
			
		||||
#define WOL_PT_LEN_MASK                 0x7f
 | 
			
		||||
#define WOL_PT0_LEN_SHIFT               0
 | 
			
		||||
#define WOL_PT1_LEN_SHIFT               8
 | 
			
		||||
#define WOL_PT2_LEN_SHIFT               16
 | 
			
		||||
#define WOL_PT3_LEN_SHIFT               24
 | 
			
		||||
#define WOL_PT4_LEN_SHIFT               0
 | 
			
		||||
#define WOL_PT5_LEN_SHIFT               8
 | 
			
		||||
#define WOL_PT6_LEN_SHIFT               16
 | 
			
		||||
 | 
			
		||||
/* Internal SRAM Partition Register */
 | 
			
		||||
#define RFDX_HEAD_ADDR_MASK		0x03FF
 | 
			
		||||
#define RFDX_HARD_ADDR_SHIFT		0
 | 
			
		||||
#define RFDX_TAIL_ADDR_MASK		0x03FF
 | 
			
		||||
#define RFDX_TAIL_ADDR_SHIFT            16
 | 
			
		||||
 | 
			
		||||
#define REG_SRAM_RFD0_INFO		0x1500
 | 
			
		||||
#define REG_SRAM_RFD1_INFO		0x1504
 | 
			
		||||
#define REG_SRAM_RFD2_INFO		0x1508
 | 
			
		||||
#define	REG_SRAM_RFD3_INFO		0x150C
 | 
			
		||||
 | 
			
		||||
#define REG_RFD_NIC_LEN			0x1510 /* In 8-bytes */
 | 
			
		||||
#define RFD_NIC_LEN_MASK		0x03FF
 | 
			
		||||
 | 
			
		||||
#define REG_SRAM_TRD_ADDR           	0x1518
 | 
			
		||||
#define TPD_HEAD_ADDR_MASK		0x03FF
 | 
			
		||||
#define TPD_HEAD_ADDR_SHIFT		0
 | 
			
		||||
#define TPD_TAIL_ADDR_MASK		0x03FF
 | 
			
		||||
#define TPD_TAIL_ADDR_SHIFT		16
 | 
			
		||||
 | 
			
		||||
#define REG_SRAM_TRD_LEN            	0x151C /* In 8-bytes */
 | 
			
		||||
#define TPD_NIC_LEN_MASK		0x03FF
 | 
			
		||||
 | 
			
		||||
#define REG_SRAM_RXF_ADDR          	0x1520
 | 
			
		||||
#define REG_SRAM_RXF_LEN            	0x1524
 | 
			
		||||
#define REG_SRAM_TXF_ADDR           	0x1528
 | 
			
		||||
#define REG_SRAM_TXF_LEN            	0x152C
 | 
			
		||||
#define REG_SRAM_TCPH_ADDR          	0x1530
 | 
			
		||||
#define REG_SRAM_PKTH_ADDR          	0x1532
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Load Ptr Register
 | 
			
		||||
 * Software sets this bit after the initialization of the head and tail */
 | 
			
		||||
#define REG_LOAD_PTR                	0x1534
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * addresses of all descriptors, as well as the following descriptor
 | 
			
		||||
 * control register, which triggers each function block to load the head
 | 
			
		||||
 * pointer to prepare for the operation. This bit is then self-cleared
 | 
			
		||||
 * after one cycle.
 | 
			
		||||
 */
 | 
			
		||||
#define REG_RX_BASE_ADDR_HI		0x1540
 | 
			
		||||
#define REG_TX_BASE_ADDR_HI		0x1544
 | 
			
		||||
#define REG_SMB_BASE_ADDR_HI		0x1548
 | 
			
		||||
#define REG_SMB_BASE_ADDR_LO		0x154C
 | 
			
		||||
#define REG_RFD0_HEAD_ADDR_LO		0x1550
 | 
			
		||||
#define REG_RFD1_HEAD_ADDR_LO		0x1554
 | 
			
		||||
#define REG_RFD2_HEAD_ADDR_LO		0x1558
 | 
			
		||||
#define REG_RFD3_HEAD_ADDR_LO		0x155C
 | 
			
		||||
#define REG_RFD_RING_SIZE		0x1560
 | 
			
		||||
#define RFD_RING_SIZE_MASK		0x0FFF
 | 
			
		||||
#define REG_RX_BUF_SIZE			0x1564
 | 
			
		||||
#define RX_BUF_SIZE_MASK		0xFFFF
 | 
			
		||||
#define REG_RRD0_HEAD_ADDR_LO		0x1568
 | 
			
		||||
#define REG_RRD1_HEAD_ADDR_LO		0x156C
 | 
			
		||||
#define REG_RRD2_HEAD_ADDR_LO		0x1570
 | 
			
		||||
#define REG_RRD3_HEAD_ADDR_LO		0x1574
 | 
			
		||||
#define REG_RRD_RING_SIZE		0x1578
 | 
			
		||||
#define RRD_RING_SIZE_MASK		0x0FFF
 | 
			
		||||
#define REG_HTPD_HEAD_ADDR_LO		0x157C
 | 
			
		||||
#define REG_NTPD_HEAD_ADDR_LO		0x1580
 | 
			
		||||
#define REG_TPD_RING_SIZE		0x1584
 | 
			
		||||
#define TPD_RING_SIZE_MASK		0xFFFF
 | 
			
		||||
#define REG_CMB_BASE_ADDR_LO		0x1588
 | 
			
		||||
 | 
			
		||||
/* RSS about */
 | 
			
		||||
#define REG_RSS_KEY0                    0x14B0
 | 
			
		||||
#define REG_RSS_KEY1                    0x14B4
 | 
			
		||||
#define REG_RSS_KEY2                    0x14B8
 | 
			
		||||
#define REG_RSS_KEY3                    0x14BC
 | 
			
		||||
#define REG_RSS_KEY4                    0x14C0
 | 
			
		||||
#define REG_RSS_KEY5                    0x14C4
 | 
			
		||||
#define REG_RSS_KEY6                    0x14C8
 | 
			
		||||
#define REG_RSS_KEY7                    0x14CC
 | 
			
		||||
#define REG_RSS_KEY8                    0x14D0
 | 
			
		||||
#define REG_RSS_KEY9                    0x14D4
 | 
			
		||||
#define REG_IDT_TABLE0                	0x14E0
 | 
			
		||||
#define REG_IDT_TABLE1                  0x14E4
 | 
			
		||||
#define REG_IDT_TABLE2                  0x14E8
 | 
			
		||||
#define REG_IDT_TABLE3                  0x14EC
 | 
			
		||||
#define REG_IDT_TABLE4                  0x14F0
 | 
			
		||||
#define REG_IDT_TABLE5                  0x14F4
 | 
			
		||||
#define REG_IDT_TABLE6                  0x14F8
 | 
			
		||||
#define REG_IDT_TABLE7                  0x14FC
 | 
			
		||||
#define REG_IDT_TABLE                   REG_IDT_TABLE0
 | 
			
		||||
#define REG_RSS_HASH_VALUE              0x15B0
 | 
			
		||||
#define REG_RSS_HASH_FLAG               0x15B4
 | 
			
		||||
#define REG_BASE_CPU_NUMBER             0x15B8
 | 
			
		||||
 | 
			
		||||
/* TXQ Control Register */
 | 
			
		||||
#define REG_TXQ_CTRL                	0x1590
 | 
			
		||||
#define	TXQ_NUM_TPD_BURST_MASK     	0xF
 | 
			
		||||
#define TXQ_NUM_TPD_BURST_SHIFT    	0
 | 
			
		||||
#define TXQ_CTRL_IP_OPTION_EN		0x10
 | 
			
		||||
#define TXQ_CTRL_EN                     0x20
 | 
			
		||||
#define TXQ_CTRL_ENH_MODE               0x40
 | 
			
		||||
#define TXQ_CTRL_LS_8023_EN		0x80
 | 
			
		||||
#define TXQ_TXF_BURST_NUM_SHIFT    	16
 | 
			
		||||
#define TXQ_TXF_BURST_NUM_MASK     	0xFFFF
 | 
			
		||||
 | 
			
		||||
/* Jumbo packet Threshold for task offload */
 | 
			
		||||
#define REG_TX_TSO_OFFLOAD_THRESH	0x1594 /* In 8-bytes */
 | 
			
		||||
#define TX_TSO_OFFLOAD_THRESH_MASK	0x07FF
 | 
			
		||||
 | 
			
		||||
#define	REG_TXF_WATER_MARK		0x1598 /* In 8-bytes */
 | 
			
		||||
#define TXF_WATER_MARK_MASK		0x0FFF
 | 
			
		||||
#define TXF_LOW_WATER_MARK_SHIFT	0
 | 
			
		||||
#define TXF_HIGH_WATER_MARK_SHIFT 	16
 | 
			
		||||
#define TXQ_CTRL_BURST_MODE_EN		0x80000000
 | 
			
		||||
 | 
			
		||||
#define REG_THRUPUT_MON_CTRL		0x159C
 | 
			
		||||
#define THRUPUT_MON_RATE_MASK		0x3
 | 
			
		||||
#define THRUPUT_MON_RATE_SHIFT		0
 | 
			
		||||
#define THRUPUT_MON_EN			0x80
 | 
			
		||||
 | 
			
		||||
/* RXQ Control Register */
 | 
			
		||||
#define REG_RXQ_CTRL                	0x15A0
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_MASK		0x3
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_SHIFT	0
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_NO		0x00
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_1M		0x01
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_10M		0x02
 | 
			
		||||
#define ASPM_THRUPUT_LIMIT_100M		0x04
 | 
			
		||||
#define RXQ1_CTRL_EN			0x10
 | 
			
		||||
#define RXQ2_CTRL_EN			0x20
 | 
			
		||||
#define RXQ3_CTRL_EN			0x40
 | 
			
		||||
#define IPV6_CHKSUM_CTRL_EN		0x80
 | 
			
		||||
#define RSS_HASH_BITS_MASK		0x00FF
 | 
			
		||||
#define RSS_HASH_BITS_SHIFT		8
 | 
			
		||||
#define RSS_HASH_IPV4			0x10000
 | 
			
		||||
#define RSS_HASH_IPV4_TCP		0x20000
 | 
			
		||||
#define RSS_HASH_IPV6			0x40000
 | 
			
		||||
#define RSS_HASH_IPV6_TCP		0x80000
 | 
			
		||||
#define RXQ_RFD_BURST_NUM_MASK		0x003F
 | 
			
		||||
#define RXQ_RFD_BURST_NUM_SHIFT		20
 | 
			
		||||
#define RSS_MODE_MASK			0x0003
 | 
			
		||||
#define RSS_MODE_SHIFT			26
 | 
			
		||||
#define RSS_NIP_QUEUE_SEL_MASK		0x1
 | 
			
		||||
#define RSS_NIP_QUEUE_SEL_SHIFT		28
 | 
			
		||||
#define RRS_HASH_CTRL_EN		0x20000000
 | 
			
		||||
#define RX_CUT_THRU_EN			0x40000000
 | 
			
		||||
#define RXQ_CTRL_EN			0x80000000
 | 
			
		||||
 | 
			
		||||
#define REG_RFD_FREE_THRESH		0x15A4
 | 
			
		||||
#define RFD_FREE_THRESH_MASK		0x003F
 | 
			
		||||
#define RFD_FREE_HI_THRESH_SHIFT	0
 | 
			
		||||
#define RFD_FREE_LO_THRESH_SHIFT	6
 | 
			
		||||
 | 
			
		||||
/* RXF flow control register */
 | 
			
		||||
#define REG_RXQ_RXF_PAUSE_THRESH    	0x15A8
 | 
			
		||||
#define RXQ_RXF_PAUSE_TH_HI_SHIFT       0
 | 
			
		||||
#define RXQ_RXF_PAUSE_TH_HI_MASK        0x0FFF
 | 
			
		||||
#define RXQ_RXF_PAUSE_TH_LO_SHIFT       16
 | 
			
		||||
#define RXQ_RXF_PAUSE_TH_LO_MASK        0x0FFF
 | 
			
		||||
 | 
			
		||||
#define REG_RXD_DMA_CTRL		0x15AC
 | 
			
		||||
#define RXD_DMA_THRESH_MASK		0x0FFF	/* In 8-bytes */
 | 
			
		||||
#define RXD_DMA_THRESH_SHIFT		0
 | 
			
		||||
#define RXD_DMA_DOWN_TIMER_MASK		0xFFFF
 | 
			
		||||
#define RXD_DMA_DOWN_TIMER_SHIFT	16
 | 
			
		||||
 | 
			
		||||
/* DMA Engine Control Register */
 | 
			
		||||
#define REG_DMA_CTRL                	0x15C0
 | 
			
		||||
#define DMA_CTRL_DMAR_IN_ORDER          0x1
 | 
			
		||||
#define DMA_CTRL_DMAR_ENH_ORDER         0x2
 | 
			
		||||
#define DMA_CTRL_DMAR_OUT_ORDER         0x4
 | 
			
		||||
#define DMA_CTRL_RCB_VALUE              0x8
 | 
			
		||||
#define DMA_CTRL_DMAR_BURST_LEN_MASK    0x0007
 | 
			
		||||
#define DMA_CTRL_DMAR_BURST_LEN_SHIFT   4
 | 
			
		||||
#define DMA_CTRL_DMAW_BURST_LEN_MASK    0x0007
 | 
			
		||||
#define DMA_CTRL_DMAW_BURST_LEN_SHIFT   7
 | 
			
		||||
#define DMA_CTRL_DMAR_REQ_PRI           0x400
 | 
			
		||||
#define DMA_CTRL_DMAR_DLY_CNT_MASK      0x001F
 | 
			
		||||
#define DMA_CTRL_DMAR_DLY_CNT_SHIFT     11
 | 
			
		||||
#define DMA_CTRL_DMAW_DLY_CNT_MASK      0x000F
 | 
			
		||||
#define DMA_CTRL_DMAW_DLY_CNT_SHIFT     16
 | 
			
		||||
#define DMA_CTRL_CMB_EN               	0x100000
 | 
			
		||||
#define DMA_CTRL_SMB_EN			0x200000
 | 
			
		||||
#define DMA_CTRL_CMB_NOW		0x400000
 | 
			
		||||
#define MAC_CTRL_SMB_DIS		0x1000000
 | 
			
		||||
#define DMA_CTRL_SMB_NOW		0x80000000
 | 
			
		||||
 | 
			
		||||
/* CMB/SMB Control Register */
 | 
			
		||||
#define REG_SMB_STAT_TIMER		0x15C4	/* 2us resolution */
 | 
			
		||||
#define SMB_STAT_TIMER_MASK		0xFFFFFF
 | 
			
		||||
#define REG_CMB_TPD_THRESH		0x15C8
 | 
			
		||||
#define CMB_TPD_THRESH_MASK		0xFFFF
 | 
			
		||||
#define REG_CMB_TX_TIMER		0x15CC	/* 2us resolution */
 | 
			
		||||
#define CMB_TX_TIMER_MASK		0xFFFF
 | 
			
		||||
 | 
			
		||||
/* Mail box */
 | 
			
		||||
#define MB_RFDX_PROD_IDX_MASK		0xFFFF
 | 
			
		||||
#define REG_MB_RFD0_PROD_IDX		0x15E0
 | 
			
		||||
#define REG_MB_RFD1_PROD_IDX		0x15E4
 | 
			
		||||
#define REG_MB_RFD2_PROD_IDX		0x15E8
 | 
			
		||||
#define REG_MB_RFD3_PROD_IDX		0x15EC
 | 
			
		||||
 | 
			
		||||
#define MB_PRIO_PROD_IDX_MASK		0xFFFF
 | 
			
		||||
#define REG_MB_PRIO_PROD_IDX		0x15F0
 | 
			
		||||
#define MB_HTPD_PROD_IDX_SHIFT		0
 | 
			
		||||
#define MB_NTPD_PROD_IDX_SHIFT		16
 | 
			
		||||
 | 
			
		||||
#define MB_PRIO_CONS_IDX_MASK		0xFFFF
 | 
			
		||||
#define REG_MB_PRIO_CONS_IDX		0x15F4
 | 
			
		||||
#define MB_HTPD_CONS_IDX_SHIFT		0
 | 
			
		||||
#define MB_NTPD_CONS_IDX_SHIFT		16
 | 
			
		||||
 | 
			
		||||
#define REG_MB_RFD01_CONS_IDX		0x15F8
 | 
			
		||||
#define MB_RFD0_CONS_IDX_MASK		0x0000FFFF
 | 
			
		||||
#define MB_RFD1_CONS_IDX_MASK		0xFFFF0000
 | 
			
		||||
#define REG_MB_RFD23_CONS_IDX		0x15FC
 | 
			
		||||
#define MB_RFD2_CONS_IDX_MASK		0x0000FFFF
 | 
			
		||||
#define MB_RFD3_CONS_IDX_MASK		0xFFFF0000
 | 
			
		||||
 | 
			
		||||
/* Interrupt Status Register */
 | 
			
		||||
#define REG_ISR    			0x1600
 | 
			
		||||
#define ISR_SMB				0x00000001
 | 
			
		||||
#define ISR_TIMER			0x00000002
 | 
			
		||||
/*
 | 
			
		||||
 * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set
 | 
			
		||||
 * in Table 51 Selene Master Control Register (Offset 0x1400).
 | 
			
		||||
 */
 | 
			
		||||
#define ISR_MANUAL         		0x00000004
 | 
			
		||||
#define ISR_HW_RXF_OV          		0x00000008 /* RXF overflow interrupt */
 | 
			
		||||
#define ISR_RFD0_UR			0x00000010 /* RFD0 under run */
 | 
			
		||||
#define ISR_RFD1_UR			0x00000020
 | 
			
		||||
#define ISR_RFD2_UR			0x00000040
 | 
			
		||||
#define ISR_RFD3_UR			0x00000080
 | 
			
		||||
#define ISR_TXF_UR			0x00000100
 | 
			
		||||
#define ISR_DMAR_TO_RST			0x00000200
 | 
			
		||||
#define ISR_DMAW_TO_RST			0x00000400
 | 
			
		||||
#define ISR_TX_CREDIT			0x00000800
 | 
			
		||||
#define ISR_GPHY			0x00001000
 | 
			
		||||
/* GPHY low power state interrupt */
 | 
			
		||||
#define ISR_GPHY_LPW           		0x00002000
 | 
			
		||||
#define ISR_TXQ_TO_RST			0x00004000
 | 
			
		||||
#define ISR_TX_PKT			0x00008000
 | 
			
		||||
#define ISR_RX_PKT_0			0x00010000
 | 
			
		||||
#define ISR_RX_PKT_1			0x00020000
 | 
			
		||||
#define ISR_RX_PKT_2			0x00040000
 | 
			
		||||
#define ISR_RX_PKT_3			0x00080000
 | 
			
		||||
#define ISR_MAC_RX			0x00100000
 | 
			
		||||
#define ISR_MAC_TX			0x00200000
 | 
			
		||||
#define ISR_UR_DETECTED			0x00400000
 | 
			
		||||
#define ISR_FERR_DETECTED		0x00800000
 | 
			
		||||
#define ISR_NFERR_DETECTED		0x01000000
 | 
			
		||||
#define ISR_CERR_DETECTED		0x02000000
 | 
			
		||||
#define ISR_PHY_LINKDOWN		0x04000000
 | 
			
		||||
#define ISR_DIS_INT			0x80000000
 | 
			
		||||
 | 
			
		||||
/* Interrupt Mask Register */
 | 
			
		||||
#define REG_IMR				0x1604
 | 
			
		||||
 | 
			
		||||
#define IMR_NORMAL_MASK		(\
 | 
			
		||||
		ISR_MANUAL	|\
 | 
			
		||||
		ISR_HW_RXF_OV	|\
 | 
			
		||||
		ISR_RFD0_UR	|\
 | 
			
		||||
		ISR_TXF_UR	|\
 | 
			
		||||
		ISR_DMAR_TO_RST	|\
 | 
			
		||||
		ISR_TXQ_TO_RST  |\
 | 
			
		||||
		ISR_DMAW_TO_RST	|\
 | 
			
		||||
		ISR_GPHY	|\
 | 
			
		||||
		ISR_TX_PKT	|\
 | 
			
		||||
		ISR_RX_PKT_0	|\
 | 
			
		||||
		ISR_GPHY_LPW    |\
 | 
			
		||||
		ISR_PHY_LINKDOWN)
 | 
			
		||||
 | 
			
		||||
#define ISR_RX_PKT 	(\
 | 
			
		||||
	ISR_RX_PKT_0    |\
 | 
			
		||||
	ISR_RX_PKT_1    |\
 | 
			
		||||
	ISR_RX_PKT_2    |\
 | 
			
		||||
	ISR_RX_PKT_3)
 | 
			
		||||
 | 
			
		||||
#define ISR_OVER	(\
 | 
			
		||||
	ISR_RFD0_UR 	|\
 | 
			
		||||
	ISR_RFD1_UR	|\
 | 
			
		||||
	ISR_RFD2_UR	|\
 | 
			
		||||
	ISR_RFD3_UR	|\
 | 
			
		||||
	ISR_HW_RXF_OV	|\
 | 
			
		||||
	ISR_TXF_UR)
 | 
			
		||||
 | 
			
		||||
#define ISR_ERROR	(\
 | 
			
		||||
	ISR_DMAR_TO_RST	|\
 | 
			
		||||
	ISR_TXQ_TO_RST  |\
 | 
			
		||||
	ISR_DMAW_TO_RST	|\
 | 
			
		||||
	ISR_PHY_LINKDOWN)
 | 
			
		||||
 | 
			
		||||
#define REG_INT_RETRIG_TIMER		0x1608
 | 
			
		||||
#define INT_RETRIG_TIMER_MASK		0xFFFF
 | 
			
		||||
 | 
			
		||||
#define REG_HDS_CTRL			0x160C
 | 
			
		||||
#define HDS_CTRL_EN			0x0001
 | 
			
		||||
#define HDS_CTRL_BACKFILLSIZE_SHIFT	8
 | 
			
		||||
#define HDS_CTRL_BACKFILLSIZE_MASK	0x0FFF
 | 
			
		||||
#define HDS_CTRL_MAX_HDRSIZE_SHIFT	20
 | 
			
		||||
#define HDS_CTRL_MAC_HDRSIZE_MASK	0x0FFF
 | 
			
		||||
 | 
			
		||||
#define REG_MAC_RX_STATUS_BIN 		0x1700
 | 
			
		||||
#define REG_MAC_RX_STATUS_END 		0x175c
 | 
			
		||||
#define REG_MAC_TX_STATUS_BIN 		0x1760
 | 
			
		||||
#define REG_MAC_TX_STATUS_END 		0x17c0
 | 
			
		||||
 | 
			
		||||
/* DEBUG ADDR */
 | 
			
		||||
#define REG_DEBUG_DATA0 		0x1900
 | 
			
		||||
#define REG_DEBUG_DATA1 		0x1904
 | 
			
		||||
 | 
			
		||||
/* PHY Control Register */
 | 
			
		||||
#define MII_BMCR			0x00
 | 
			
		||||
#define BMCR_SPEED_SELECT_MSB		0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
 | 
			
		||||
#define BMCR_COLL_TEST_ENABLE		0x0080  /* Collision test enable */
 | 
			
		||||
#define BMCR_FULL_DUPLEX		0x0100  /* FDX =1, half duplex =0 */
 | 
			
		||||
#define BMCR_RESTART_AUTO_NEG		0x0200  /* Restart auto negotiation */
 | 
			
		||||
#define BMCR_ISOLATE			0x0400  /* Isolate PHY from MII */
 | 
			
		||||
#define BMCR_POWER_DOWN			0x0800  /* Power down */
 | 
			
		||||
#define BMCR_AUTO_NEG_EN		0x1000  /* Auto Neg Enable */
 | 
			
		||||
#define BMCR_SPEED_SELECT_LSB		0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
 | 
			
		||||
#define BMCR_LOOPBACK			0x4000  /* 0 = normal, 1 = loopback */
 | 
			
		||||
#define BMCR_RESET			0x8000  /* 0 = normal, 1 = PHY reset */
 | 
			
		||||
#define BMCR_SPEED_MASK			0x2040
 | 
			
		||||
#define BMCR_SPEED_1000			0x0040
 | 
			
		||||
#define BMCR_SPEED_100			0x2000
 | 
			
		||||
#define BMCR_SPEED_10			0x0000
 | 
			
		||||
 | 
			
		||||
/* PHY Status Register */
 | 
			
		||||
#define MII_BMSR			0x01
 | 
			
		||||
#define BMMSR_EXTENDED_CAPS		0x0001  /* Extended register capabilities */
 | 
			
		||||
#define BMSR_JABBER_DETECT		0x0002  /* Jabber Detected */
 | 
			
		||||
#define BMSR_LINK_STATUS		0x0004  /* Link Status 1 = link */
 | 
			
		||||
#define BMSR_AUTONEG_CAPS		0x0008  /* Auto Neg Capable */
 | 
			
		||||
#define BMSR_REMOTE_FAULT		0x0010  /* Remote Fault Detect */
 | 
			
		||||
#define BMSR_AUTONEG_COMPLETE		0x0020  /* Auto Neg Complete */
 | 
			
		||||
#define BMSR_PREAMBLE_SUPPRESS		0x0040  /* Preamble may be suppressed */
 | 
			
		||||
#define BMSR_EXTENDED_STATUS		0x0100  /* Ext. status info in Reg 0x0F */
 | 
			
		||||
#define BMSR_100T2_HD_CAPS		0x0200  /* 100T2 Half Duplex Capable */
 | 
			
		||||
#define BMSR_100T2_FD_CAPS		0x0400  /* 100T2 Full Duplex Capable */
 | 
			
		||||
#define BMSR_10T_HD_CAPS		0x0800  /* 10T   Half Duplex Capable */
 | 
			
		||||
#define BMSR_10T_FD_CAPS		0x1000  /* 10T   Full Duplex Capable */
 | 
			
		||||
#define BMSR_100X_HD_CAPS		0x2000  /* 100X  Half Duplex Capable */
 | 
			
		||||
#define BMMII_SR_100X_FD_CAPS		0x4000  /* 100X  Full Duplex Capable */
 | 
			
		||||
#define BMMII_SR_100T4_CAPS		0x8000  /* 100T4 Capable */
 | 
			
		||||
 | 
			
		||||
#define MII_PHYSID1			0x02
 | 
			
		||||
#define MII_PHYSID2			0x03
 | 
			
		||||
 | 
			
		||||
/* Autoneg Advertisement Register */
 | 
			
		||||
#define MII_ADVERTISE			0x04
 | 
			
		||||
#define ADVERTISE_SPEED_MASK		0x01E0
 | 
			
		||||
#define ADVERTISE_DEFAULT_CAP		0x0DE0
 | 
			
		||||
 | 
			
		||||
/* 1000BASE-T Control Register */
 | 
			
		||||
#define MII_GIGA_CR			0x09
 | 
			
		||||
#define GIGA_CR_1000T_REPEATER_DTE	0x0400  /* 1=Repeater/switch device port 0=DTE device */
 | 
			
		||||
 | 
			
		||||
#define GIGA_CR_1000T_MS_VALUE		0x0800  /* 1=Configure PHY as Master 0=Configure PHY as Slave */
 | 
			
		||||
#define GIGA_CR_1000T_MS_ENABLE		0x1000  /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */
 | 
			
		||||
#define GIGA_CR_1000T_TEST_MODE_NORMAL	0x0000  /* Normal Operation */
 | 
			
		||||
#define GIGA_CR_1000T_TEST_MODE_1	0x2000  /* Transmit Waveform test */
 | 
			
		||||
#define GIGA_CR_1000T_TEST_MODE_2	0x4000  /* Master Transmit Jitter test */
 | 
			
		||||
#define GIGA_CR_1000T_TEST_MODE_3	0x6000  /* Slave Transmit Jitter test */
 | 
			
		||||
#define GIGA_CR_1000T_TEST_MODE_4	0x8000	/* Transmitter Distortion test */
 | 
			
		||||
#define GIGA_CR_1000T_SPEED_MASK	0x0300
 | 
			
		||||
#define GIGA_CR_1000T_DEFAULT_CAP	0x0300
 | 
			
		||||
 | 
			
		||||
/* PHY Specific Status Register */
 | 
			
		||||
#define MII_GIGA_PSSR			0x11
 | 
			
		||||
#define GIGA_PSSR_SPD_DPLX_RESOLVED	0x0800  /* 1=Speed & Duplex resolved */
 | 
			
		||||
#define GIGA_PSSR_DPLX			0x2000  /* 1=Duplex 0=Half Duplex */
 | 
			
		||||
#define GIGA_PSSR_SPEED			0xC000  /* Speed, bits 14:15 */
 | 
			
		||||
#define GIGA_PSSR_10MBS			0x0000  /* 00=10Mbs */
 | 
			
		||||
#define GIGA_PSSR_100MBS		0x4000  /* 01=100Mbs */
 | 
			
		||||
#define GIGA_PSSR_1000MBS		0x8000  /* 10=1000Mbs */
 | 
			
		||||
 | 
			
		||||
/* PHY Interrupt Enable Register */
 | 
			
		||||
#define MII_IER				0x12
 | 
			
		||||
#define IER_LINK_UP			0x0400
 | 
			
		||||
#define IER_LINK_DOWN			0x0800
 | 
			
		||||
 | 
			
		||||
/* PHY Interrupt Status Register */
 | 
			
		||||
#define MII_ISR				0x13
 | 
			
		||||
#define ISR_LINK_UP			0x0400
 | 
			
		||||
#define ISR_LINK_DOWN			0x0800
 | 
			
		||||
 | 
			
		||||
/* Cable-Detect-Test Control Register */
 | 
			
		||||
#define MII_CDTC			0x16
 | 
			
		||||
#define CDTC_EN_OFF			0   /* sc */
 | 
			
		||||
#define CDTC_EN_BITS			1
 | 
			
		||||
#define CDTC_PAIR_OFF			8
 | 
			
		||||
#define CDTC_PAIR_BIT			2
 | 
			
		||||
 | 
			
		||||
/* Cable-Detect-Test Status Register */
 | 
			
		||||
#define MII_CDTS			0x1C
 | 
			
		||||
#define CDTS_STATUS_OFF			8
 | 
			
		||||
#define CDTS_STATUS_BITS		2
 | 
			
		||||
#define CDTS_STATUS_NORMAL		0
 | 
			
		||||
#define CDTS_STATUS_SHORT		1
 | 
			
		||||
#define CDTS_STATUS_OPEN		2
 | 
			
		||||
#define CDTS_STATUS_INVALID		3
 | 
			
		||||
 | 
			
		||||
#define MII_DBG_ADDR			0x1D
 | 
			
		||||
#define MII_DBG_DATA			0x1E
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_0			0x0
 | 
			
		||||
#define ANA_RESTART_CAL			0x0001
 | 
			
		||||
#define ANA_MANUL_SWICH_ON_SHIFT	0x1
 | 
			
		||||
#define ANA_MANUL_SWICH_ON_MASK		0xF
 | 
			
		||||
#define ANA_MAN_ENABLE			0x0020
 | 
			
		||||
#define ANA_SEL_HSP			0x0040
 | 
			
		||||
#define ANA_EN_HB			0x0080
 | 
			
		||||
#define ANA_EN_HBIAS			0x0100
 | 
			
		||||
#define ANA_OEN_125M			0x0200
 | 
			
		||||
#define ANA_EN_LCKDT			0x0400
 | 
			
		||||
#define ANA_LCKDT_PHY			0x0800
 | 
			
		||||
#define ANA_AFE_MODE			0x1000
 | 
			
		||||
#define ANA_VCO_SLOW			0x2000
 | 
			
		||||
#define ANA_VCO_FAST			0x4000
 | 
			
		||||
#define ANA_SEL_CLK125M_DSP		0x8000
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_4			0x4
 | 
			
		||||
#define ANA_IECHO_ADJ_MASK		0xF
 | 
			
		||||
#define ANA_IECHO_ADJ_3_SHIFT		0
 | 
			
		||||
#define ANA_IECHO_ADJ_2_SHIFT		4
 | 
			
		||||
#define ANA_IECHO_ADJ_1_SHIFT		8
 | 
			
		||||
#define ANA_IECHO_ADJ_0_SHIFT		12
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_5			0x5
 | 
			
		||||
#define ANA_SERDES_CDR_BW_SHIFT		0
 | 
			
		||||
#define ANA_SERDES_CDR_BW_MASK		0x3
 | 
			
		||||
#define ANA_MS_PAD_DBG			0x0004
 | 
			
		||||
#define ANA_SPEEDUP_DBG			0x0008
 | 
			
		||||
#define ANA_SERDES_TH_LOS_SHIFT		4
 | 
			
		||||
#define ANA_SERDES_TH_LOS_MASK		0x3
 | 
			
		||||
#define ANA_SERDES_EN_DEEM		0x0040
 | 
			
		||||
#define ANA_SERDES_TXELECIDLE		0x0080
 | 
			
		||||
#define ANA_SERDES_BEACON		0x0100
 | 
			
		||||
#define ANA_SERDES_HALFTXDR		0x0200
 | 
			
		||||
#define ANA_SERDES_SEL_HSP		0x0400
 | 
			
		||||
#define ANA_SERDES_EN_PLL		0x0800
 | 
			
		||||
#define ANA_SERDES_EN			0x1000
 | 
			
		||||
#define ANA_SERDES_EN_LCKDT		0x2000
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_11			0xB
 | 
			
		||||
#define ANA_PS_HIB_EN			0x8000
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_18			0x12
 | 
			
		||||
#define ANA_TEST_MODE_10BT_01SHIFT	0
 | 
			
		||||
#define ANA_TEST_MODE_10BT_01MASK	0x3
 | 
			
		||||
#define ANA_LOOP_SEL_10BT		0x0004
 | 
			
		||||
#define ANA_RGMII_MODE_SW		0x0008
 | 
			
		||||
#define ANA_EN_LONGECABLE		0x0010
 | 
			
		||||
#define ANA_TEST_MODE_10BT_2		0x0020
 | 
			
		||||
#define ANA_EN_10BT_IDLE		0x0400
 | 
			
		||||
#define ANA_EN_MASK_TB			0x0800
 | 
			
		||||
#define ANA_TRIGGER_SEL_TIMER_SHIFT	12
 | 
			
		||||
#define ANA_TRIGGER_SEL_TIMER_MASK	0x3
 | 
			
		||||
#define ANA_INTERVAL_SEL_TIMER_SHIFT	14
 | 
			
		||||
#define ANA_INTERVAL_SEL_TIMER_MASK	0x3
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_41			0x29
 | 
			
		||||
#define ANA_TOP_PS_EN			0x8000
 | 
			
		||||
 | 
			
		||||
#define MII_ANA_CTRL_54			0x36
 | 
			
		||||
#define ANA_LONG_CABLE_TH_100_SHIFT	0
 | 
			
		||||
#define ANA_LONG_CABLE_TH_100_MASK	0x3F
 | 
			
		||||
#define ANA_DESERVED			0x0040
 | 
			
		||||
#define ANA_EN_LIT_CH			0x0080
 | 
			
		||||
#define ANA_SHORT_CABLE_TH_100_SHIFT	8
 | 
			
		||||
#define ANA_SHORT_CABLE_TH_100_MASK	0x3F
 | 
			
		||||
#define ANA_BP_BAD_LINK_ACCUM		0x4000
 | 
			
		||||
#define ANA_BP_SMALL_BW			0x8000
 | 
			
		||||
 | 
			
		||||
#endif /*_ATL1C_HW_H_*/
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue