## Automatically generated incremental diff
## From: linux-2.5.70-bk10
## To: linux-2.5.70-bk11
## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $
diff -urN linux-2.5.70-bk10/Documentation/00-INDEX linux-2.5.70-bk11/Documentation/00-INDEX
--- linux-2.5.70-bk10/Documentation/00-INDEX 2003-05-26 18:00:26.000000000 -0700
+++ linux-2.5.70-bk11/Documentation/00-INDEX 2003-06-06 04:38:19.000000000 -0700
@@ -182,6 +182,8 @@
- short guide on how to set up and use the RAM disk.
riscom8.txt
- notes on using the RISCom/8 multi-port serial driver.
+rocket.txt
+ - info on installing/using the Comtrol RocketPort multiport serial driver
rtc.txt
- notes on how to use the Real Time Clock (aka CMOS clock) driver.
s390/
diff -urN linux-2.5.70-bk10/Documentation/DocBook/Makefile linux-2.5.70-bk11/Documentation/DocBook/Makefile
--- linux-2.5.70-bk10/Documentation/DocBook/Makefile 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/Documentation/DocBook/Makefile 2003-06-06 04:38:19.000000000 -0700
@@ -11,7 +11,8 @@
kernel-locking.sgml via-audio.sgml mousedrivers.sgml \
deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
- kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml
+ kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
+ gadget.sgml
###
# The build process is as follows (targets):
diff -urN linux-2.5.70-bk10/Documentation/DocBook/gadget.tmpl linux-2.5.70-bk11/Documentation/DocBook/gadget.tmpl
--- linux-2.5.70-bk10/Documentation/DocBook/gadget.tmpl 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk11/Documentation/DocBook/gadget.tmpl 2003-06-06 04:38:19.000000000 -0700
@@ -0,0 +1,966 @@
+
+
+
+ USB Gadget API for Linux
+ 02 June 2003
+ 02 June 2003
+
+
+ Permission is granted to copy, distribute, and/or modify
+ this document under the terms of the GNU Free Documentation
+ License, version 1.2, or any later version published by the
+ Free Software Foundation; with the Invariant Sections being
+ the "GNU Free Documentation License",
+ no Front-Cover Texts,
+ and
+ no Back-Cover Texts.
+
+
+ This documentation 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 Free Documentation License for more details.
+
+
+ Note that certain sections of this document are merged
+ into Linux kernel source code.
+ That content is the bulk of
+ and
+ ,
+ where the "GNU Free Documentation License" is identified
+ as an alternate licence for its documentation.
+
+
+
+
+ 2003
+ David Brownell
+
+
+
+ David
+ Brownell
+
+ dbrownell@users.sourceforge.net
+
+
+
+
+
+
+Introduction
+
+This document presents a Linux-USB "Gadget"
+kernel mode
+API, for use within peripherals and other USB devices
+that embed Linux.
+It provides an overview of the API structure,
+and shows how that fits into a system development project.
+This is the first such API released on Linux to address
+a number of important problems, including:
+
+
+ Supports USB 2.0, for high speed devices which
+ can stream data at several dozen megabytes per second.
+
+ Handles devices with dozens of endpoints just as
+ well as ones with just two fixed-function ones. Gadget drivers
+ can be written so they're easy to port to new hardware.
+
+ Flexible enough to expose more complex USB device
+ capabilities such as multiple configurations, multiple interfaces,
+ composite devices,
+ and alternate interface settings.
+
+ Sharing data structures and API models with the
+ Linux-USB host side API. This looks forward to USB "On-The-Go"
+ (OTG) and similar more-symmetric frameworks.
+
+ Minimalist, so it's easier to support new device
+ controller hardware. I/O processing doesn't imply large
+ demands for memory or CPU resources.
+
+
+
+
+Most Linux developers will not be able to use this API, since they
+have USB "host" hardware in a PC, workstation, or server.
+Linux users with embedded systems are more likely to
+have USB peripheral hardware.
+To distinguish drivers running inside such hardware from the
+more familiar Linux "USB device drivers",
+which are host side proxies for the real USB devices,
+a different term is used:
+the drivers inside the peripherals are "USB gadget drivers".
+In USB protocol interactions, the device driver is the master
+(or "client driver")
+and the gadget driver is the slave (or "function driver").
+
+
+The gadget API resembles the host side Linux-USB API in that both
+use queues of request objects to package I/O buffers, and those requests
+may be submitted or canceled.
+They share common definitions for the standard USB
+Chapter 9 messages, structures, and constants.
+Also, both APIs bind and unbind drivers to devices.
+The APIs differ in detail, since the host side's current
+URB framework exposes a number of implementation details
+and assumptions that are inappropriate for a gadget API.
+While the model for control transfers and configuration
+management is necessarily different (one side is a hardware-neutral master,
+the other is a hardware-aware slave), the endpoint I/0 API used here
+should also be usable for an overhead-reduced host side API.
+
+
+
+
+Structure of Gadget Drivers
+
+A system running inside a USB peripheral
+normally has at least three layers inside the kernel to handle
+USB protocol processing, and may have additional layers in
+user space code.
+The "gadget" API is used by the middle layer to interact
+with the lowest level (which directly handles hardware).
+
+
+In Linux, from the bottom up, these layers are:
+
+
+
+
+
+ USB Controller Driver
+
+
+ This is the lowest software level.
+ It is the only layer that talks to hardware,
+ through registers, fifos, dma, irqs, and the like.
+ The <linux/usb_gadget.h> API abstracts
+ the peripheral controller endpoint hardware.
+ That hardware is exposed through endpoint objects, which accept
+ streams of IN/OUT buffers, and through callbacks that interact
+ with gadget drivers.
+ Since normal USB devices only have one upstream
+ port, they only have one of these drivers.
+ The controller driver can support any number of different
+ gadget drivers, but only one of them can be used at a time.
+
+
+ Examples of such controller hardware include
+ the PCI-based NetChip 2280 USB 2.0 high speed controller,
+ the SA-11x0 or PXA-25x UDC (found within many PDAs),
+ and a variety of other products.
+
+
+
+
+ Gadget Driver
+
+
+ The lower boundary of this driver implements hardware-neutral
+ USB functions, using calls to the controller driver.
+ Because such hardware varies widely in capabilities and restrictions,
+ the gadget driver is normally configured at compile time
+ to work with endpoints supported by one particular controller.
+ Gadget drivers may be portable to several different controllers,
+ using conditional compilation.
+ Gadget driver responsibilities include:
+
+
+ handling setup requests (ep0 protocol responses)
+ possibly including class-specific functionality
+
+ returning configuration and string descriptors
+
+ (re)setting configurations and interface
+ altsettings, including enabling and configuring endpoints
+
+ handling life cycle events, such as managing
+ bindings
+ to hardware, and disconnection from the USB host.
+
+ managing IN and OUT transfers on all currently
+ enabled endpoints
+
+
+
+
+ Such drivers may be modules of proprietary code, although
+ that approach is discouraged in the Linux community.
+
+
+
+
+ Upper Level
+
+
+ Most gadget drivers have an upper boundary that connects
+ to some Linux driver or framework in Linux.
+ Through that boundary flows the data which the gadget driver
+ produces and/or consumes through protocol transfers over USB.
+ Examples include:
+
+
+ user mode code, using generic (gadgetfs)
+ or application specific files in
+ /dev
+
+ networking subsystem (for network gadgets,
+ like the CDC Ethernet Model gadget driver)
+
+ data capture drivers, perhaps video4Linux or
+ a scanner driver; or test and measurement hardware.
+
+ input subsystem (for HID gadgets)
+
+ sound subsystem (for audio gadgets)
+
+ file system (for PTP gadgets)
+
+ block i/o subsystem (for usb-storage gadgets)
+
+ ... and more
+
+
+
+
+ Additional Layers
+
+
+ Other layers may exist.
+ These could include kernel layers, such as network protocol stacks,
+ as well as user mode applications building on standard POSIX
+ system call APIs such as
+ open(), close(),
+ read() and write().
+ On newer systems, POSIX Async I/O calls may be an option.
+ Such user mode code will not necessarily be subject to
+ the GNU General Public License (GPL).
+
+
+
+
+
+
+Over time, reusable utilities should evolve to help make some
+gadget driver tasks simpler. An example of particular interest
+is code implementing standard USB-IF protocols for
+HID, networking, storage, or audio classes.
+Some developers are interested in KDB or KGDB hooks, to let
+target hardware be remotely debugged.
+Most such USB protocol code doesn't need to be hardware-specific,
+any more than network protocols like X11, HTTP, or NFS are.
+Such interface drivers might be combined, to support composite devices.
+
+
+
+
+
+Kernel Mode Gadget API
+
+Gadget drivers declare themselves through a
+struct usb_gadget_driver, which is responsible for
+most parts of enumeration for a struct usb_gadget.
+The response to a set_configuration usually involves
+enabling one or more of the struct usb_ep objects
+exposed by the gadget, and submitting one or more
+struct usb_request buffers to transfer data.
+Understand those four data types, and their operations, and
+you will understand how this API works.
+
+
+Incomplete Data Type Descriptions
+
+This documentation was prepared using the standard Linux
+kernel docproc tool, which turns text
+and in-code comments into SGML DocBook and then into usable
+formats such as HTML or PDF.
+Other than the "Chapter 9" data types, most of the significant
+data types and functions are described here.
+
+
+However, docproc does not understand all the C constructs
+that are used, so some relevant information is likely omitted from
+what you are reading.
+One example of such information is several per-request flags.
+You'll have to read the header file, and use example source
+code (such as that for "Gadget Zero"), to fully understand the API.
+
+
+The part of the API implementing some basic
+driver capabilities is specific to the version of the
+Linux kernel that's in use.
+The 2.5 kernel includes a driver model
+framework that has no analogue on earlier kernels;
+so those parts of the gadget API are not fully portable.
+(They are implemented on 2.4 kernels, but in a different way.)
+The driver model state is another part of this API that is
+ignored by the kerneldoc tools.
+
+
+
+The core API does not expose
+every possible hardware feature, only the most widely available ones.
+There are significant hardware features, such as device-to-device DMA
+(without temporary storage in a memory buffer)
+that would be added using hardware-specific APIs.
+
+
+This API expects drivers to use conditional compilation to handle
+endpoint capabilities of different hardware.
+Those tend to have arbitrary restrictions, relating to
+transfer types, addressing, packet sizes, buffering, and availability.
+As a rule, such differences only matter for "endpoint zero" logic
+that handles device configuration and management.
+The API only supports limited run-time
+detection of capabilities, through naming conventions for endpoints.
+Although a gadget driver could scan the endpoints available to it and
+choose to map those capabilities onto driver functionality in some way,
+few drivers will want to reconfigure themselves at run-time.
+
+
+Like the Linux-USB host side API, this API exposes
+the "chunky" nature of USB messages: I/O requests are in terms
+of one or more "packets", and packet boundaries are visible to drivers.
+Compared to RS-232 serial protocols, USB resembles
+synchronous protocols like HDLC
+(N bytes per frame, multipoint addressing from the host)
+more than asynchronous ones
+(tty style, like 8 bytes, no parity, one stop bit).
+So for example the controller drivers won't buffer
+two single byte writes into a single two-byte USB IN packet,
+although gadget drivers may do so when they implement
+protocols where packet boundaries (and "short packets")
+are not significant.
+
+
+Driver Life Cycle
+
+Gadget drivers make endpoint I/O requests to hardware without
+needing to know many details of the hardware, but driver
+setup/configuration code needs to handle some differences.
+Use the API like this:
+
+
+
+
+Register a driver for the particular device side
+usb controller hardware,
+such as the net2280 on PCI (USB 2.0),
+sa11x0 or pxa25x as found in Linux PDAs,
+and so on.
+At this point the device is logically in the USB ch9 initial state
+("attached"), drawing no power and not usable
+(since it does not yet support enumeration).
+
+
+Register a gadget driver that implements some higher level
+device function. That will then bind() to a usb_gadget.
+
+
+The hardware driver can now start enumerating.
+The steps it handles are to accept USB power and set_address requests.
+Other steps are handled by the gadget driver.
+If the gadget driver module is unloaded before the host starts to
+enumerate, steps before step 7 are skipped.
+
+
+The gadget driver's setup() call returns usb descriptors,
+based both on what the bus interface hardware provides and on the
+functionality being implemented.
+That can involve alternate settings or configurations,
+unless the hardware prevents such operation.
+
+
+The gadget driver handles the last step of enumeration,
+when the USB host issues a set_configuration call.
+It enables all endpoints used in that configuration,
+with all interfaces in their default settings.
+That involves using a list of the hardware's endpoints, enabling each
+endpoint according to its descriptor.
+
+
+Do real work and perform data transfers, possibly involving
+changes to interface settings or switching to new configurations, until the
+device is disconnect()ed from the host.
+Queue any number of transfer requests to each endpoint.
+The drivers then go back to step 3 (above).
+
+
+When the gadget driver module is being unloaded,
+the driver unbind() callback is issued. That lets the controller
+driver be unloaded.
+
+
+
+
+Drivers will normally be arranged so that just loading the
+gadget driver module (or statically linking it into a Linux kernel)
+allows the peripheral device to be enumerated.
+Note that at this lowest level there are no policies about how
+ep0 configuration logic is implemented,
+except that it should obey USB specifications.
+Such issues are in the domain of gadget drivers,
+including knowing about implementation constraints
+imposed by some USB controllers
+or understanding that composite devices might happen to
+be built by integrating reusable components.
+
+
+
+
+USB 2.0 Chapter 9 Types and Constants
+
+Gadget drivers
+rely on common USB structures and constants
+defined in the
+<linux/usb_ch9.h>
+header file, which is standard in Linux 2.5 kernels.
+These are the same types and constants used by host
+side drivers.
+
+
+!Iinclude/linux/usb_ch9.h
+
+
+Core Objects and Methods
+
+These are declared in
+<linux/usb_gadget.h>,
+and are used by gadget drivers to interact with
+USB peripheral controller drivers.
+
+
+
+
+!Iinclude/linux/usb_gadget.h
+
+
+Optional Utilities
+
+The core API is sufficient for writing a USB Gadget Driver,
+but some optional utilities are provided to simplify common tasks.
+
+
+!Edrivers/usb/gadget/usbstring.c
+
+
+
+
+Peripheral Controller Drivers
+
+The first hardware supporting this API is the NetChip 2280
+controller, which supports USB 2.0 high speed and is based on PCI.
+This is the net2280 driver module.
+The driver supports Linux kernel versions 2.4 and 2.5;
+contact NetChip Technologies for development boards and product
+information.
+
+
+
+
+A partial USB simulator,
+the dummy_hcd driver, is available.
+It can act like a net2280, a pxa25x, or an sa11x0 in terms
+of available endpoints and device speeds; and it simulates
+control, bulk, and to some extent interrupt transfers.
+That lets you develop some parts of a gadget driver on a normal PC,
+without any special hardware, and perhaps with the assistance
+of tools such as GDB running with User Mode Linux.
+At least one person has expressed interest in adapting that
+approach, hooking it up to a simulator for a microcontroller.
+Such simulators can help debug subsystems where the runtime hardware
+is unfriendly to software development, or is not yet available.
+
+
+Support for other controllers is expected to be developed
+and contributed
+over time, as this driver framework evolves.
+
+
+
+
+Gadget Drivers
+
+In addition to Gadget Zero
+(used primarily for testing and development with drivers
+for usb controller hardware), other gadget drivers exist.
+
+
+There's an ethernet gadget
+driver, which implements one of the most useful
+Communications Device Class models.
+One of the standards for cable modem interoperability even
+specifies the use of this ethernet model as one of two
+mandatory options.
+Gadgets using this code look to a USB host as if they're
+an Ethernet adapter.
+It provides access to a network where the gadget's CPU is one host,
+which could easily be bridging, routing, or firewalling
+access to other networks.
+
+
+There is also support for user mode gadget drivers,
+using gadgetfs.
+This provides a User Mode API that presents
+each endpoint as a single file descriptor. I/O is done using
+normal read() and read() calls.
+Familiar tools like GDB and pthreads can be used to
+develop and debug user mode drivers, so that once a robust
+controller driver is available many applications for it
+won't require new kernel mode software.
+
+
+Support for other kinds of gadget is expected to
+be developed and contributed
+over time, as this driver framework evolves.
+
+
+
+
+
+
+GNU Free Documentation License
+Version 1.2, November 2002
+
+
+ Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or
+other functional and useful document "free" in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it, with
+or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible for
+modifications made by others.
+
+This License is a kind of "copyleft", which means that derivative
+works of the document must themselves be free in the same sense. It
+complements the GNU General Public License, which is a copyleft license
+designed for free software.
+
+We have designed this License in order to use it for manuals for
+free software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does. But this License is not limited to software manuals; it
+can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book. We recommend this License
+principally for works whose purpose is instruction or reference.
+
+
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in
+any medium, that contains a notice placed by the copyright holder saying
+it can be distributed under the terms of this License. Such a notice
+grants a world-wide, royalty-free license, unlimited in duration, to use
+that work under the conditions stated herein. The "Document", below,
+refers to any such manual or work. Any member of the public is a
+licensee, and is addressed as "you". You accept the license if you
+copy, modify or distribute the work in a way requiring permission under
+copyright law.
+
+A "Modified Version" of the Document means any
+work containing the Document or a portion of it, either copied verbatim,
+or with modifications and/or translated into another language.
+
+A "Secondary Section" is a named appendix or
+a front-matter section of the Document that deals exclusively with the
+relationship of the publishers or authors of the Document to the
+Document's overall subject (or to related matters) and contains nothing
+that could fall directly within that overall subject. (Thus, if the
+Document is in part a textbook of mathematics, a Secondary Section may
+not explain any mathematics.) The relationship could be a matter of
+historical connection with the subject or with related matters, or of
+legal, commercial, philosophical, ethical or political position
+regarding them.
+
+The "Invariant Sections" are certain Secondary
+Sections whose titles are designated, as being those of Invariant
+Sections, in the notice that says that the Document is released under
+this License. If a section does not fit the above definition of
+Secondary then it is not allowed to be designated as Invariant. The
+Document may contain zero Invariant Sections. If the Document does not
+identify any Invariant Sections then there are none.
+
+The "Cover Texts" are certain short passages of
+text that are listed, as Front-Cover Texts or Back-Cover Texts, in the
+notice that says that the Document is released under this License. A
+Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at
+most 25 words.
+
+A "Transparent" copy of the Document means a
+machine-readable copy, represented in a format whose specification is
+available to the general public, that is suitable for revising the
+document straightforwardly with generic text editors or (for images
+composed of pixels) generic paint programs or (for drawings) some widely
+available drawing editor, and that is suitable for input to text
+formatters or for automatic translation to a variety of formats suitable
+for input to text formatters. A copy made in an otherwise Transparent
+file format whose markup, or absence of markup, has been arranged to
+thwart or discourage subsequent modification by readers is not
+Transparent. An image format is not Transparent if used for any
+substantial amount of text. A copy that is not "Transparent" is called
+"Opaque".
+
+Examples of suitable formats for Transparent copies include plain
+ASCII without markup, Texinfo input format, LaTeX input format, SGML or
+XML using a publicly available DTD, and standard-conforming simple HTML,
+PostScript or PDF designed for human modification. Examples of
+transparent image formats include PNG, XCF and JPG. Opaque formats
+include proprietary formats that can be read and edited only by
+proprietary word processors, SGML or XML for which the DTD and/or
+processing tools are not generally available, and the machine-generated
+HTML, PostScript or PDF produced by some word processors for output
+purposes only.
+
+The "Title Page" means, for a printed book,
+the title page itself, plus such following pages as are needed to hold,
+legibly, the material this License requires to appear in the title page.
+For works in formats which do not have any title page as such, "Title
+Page" means the text near the most prominent appearance of the work's
+title, preceding the beginning of the body of the text.
+
+A section "Entitled XYZ" means a named subunit
+of the Document whose title either is precisely XYZ or contains XYZ in
+parentheses following text that translates XYZ in another language.
+(Here XYZ stands for a specific section name mentioned below, such as
+"Acknowledgements", "Dedications", "Endorsements", or "History".) To
+"Preserve the Title" of such a section when you modify the Document
+means that it remains a section "Entitled XYZ" according to this
+definition.
+
+The Document may include Warranty Disclaimers next to the notice
+which states that this License applies to the Document. These Warranty
+Disclaimers are considered to be included by reference in this License,
+but only as regards disclaiming warranties: any other implication that
+these Warranty Disclaimers may have is void and has no effect on the
+meaning of this License.
+
+
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies to
+the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License. You may not use
+technical measures to obstruct or control the reading or further copying
+of the copies you make or distribute. However, you may accept
+compensation in exchange for copies. If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+
+You may also lend copies, under the same conditions stated above,
+and you may publicly display copies.
+
+
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly
+have printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover Texts:
+Front-Cover Texts on the front cover, and Back-Cover Texts on the back
+cover. Both covers must also clearly and legibly identify you as the
+publisher of these copies. The front cover must present the full title
+with all words of the title equally prominent and visible. You may add
+other material on the covers in addition. Copying with changes limited
+to the covers, as long as they preserve the title of the Document and
+satisfy these conditions, can be treated as verbatim copying in other
+respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document
+numbering more than 100, you must either include a machine-readable
+Transparent copy along with each Opaque copy, or state in or with each
+Opaque copy a computer-network location from which the general
+network-using public has access to download using public-standard
+network protocols a complete Transparent copy of the Document, free of
+added material. If you use the latter option, you must take reasonably
+prudent steps, when you begin distribution of Opaque copies in quantity,
+to ensure that this Transparent copy will remain thus accessible at the
+stated location until at least one year after the last time you
+distribute an Opaque copy (directly or through your agents or retailers)
+of that edition to the public.
+
+It is requested, but not required, that you contact the authors of
+the Document well before redistributing any large number of copies, to
+give them a chance to provide you with an updated version of the
+Document.
+
+
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document
+under the conditions of sections 2 and 3 above, provided that you
+release the Modified Version under precisely this License, with the
+Modified Version filling the role of the Document, thus licensing
+distribution and modification of the Modified Version to whoever
+possesses a copy of it. In addition, you must do these things in the
+Modified Version:
+
+
+Use in the Title Page (and on the covers, if any) a
+ title distinct from that of the Document, and from those of previous
+ versions (which should, if there were any, be listed in the History
+ section of the Document). You may use the same title as a previous
+ version if the original publisher of that version gives permission.
+
+List on the Title Page, as authors, one or more
+ persons or entities responsible for authorship of the modifications in
+ the Modified Version, together with at least five of the principal
+ authors of the Document (all of its principal authors, if it has fewer
+ than five), unless they release you from this requirement.
+
+State on the Title page the name of the publisher of
+ the Modified Version, as the publisher.
+Preserve all the copyright notices of the Document.
+
+Add an appropriate copyright notice for your
+ modifications adjacent to the other copyright notices.
+
+Include, immediately after the copyright notices, a
+ license notice giving the public permission to use the Modified
+ Version under the terms of this License, in the form shown in the
+ Addendum below.
+
+Preserve in that license notice the full lists of
+ Invariant Sections and required Cover Texts given in the Document's
+ license notice.
+Include an unaltered copy of this License.
+
+Preserve the section Entitled "History", Preserve its
+ Title, and add to it an item stating at least the title, year, new
+ authors, and publisher of the Modified Version as given on the Title
+ Page. If there is no section Entitled "History" in the Document,
+ create one stating the title, year, authors, and publisher of the
+ Document as given on its Title Page, then add an item describing the
+ Modified Version as stated in the previous sentence.
+
+Preserve the network location, if any, given in the
+ Document for public access to a Transparent copy of the Document, and
+ likewise the network locations given in the Document for previous
+ versions it was based on. These may be placed in the "History"
+ section. You may omit a network location for a work that was
+ published at least four years before the Document itself, or if the
+ original publisher of the version it refers to gives permission.
+
+For any section Entitled "Acknowledgements" or
+ "Dedications", Preserve the Title of the section, and preserve in the
+ section all the substance and tone of each of the contributor
+ acknowledgements and/or dedications given therein.
+
+Preserve all the Invariant Sections of the Document,
+ unaltered in their text and in their titles. Section numbers or the
+ equivalent are not considered part of the section titles.
+
+Delete any section Entitled "Endorsements".
+ Such a section may not be included in the Modified Version.
+
+Do not retitle any existing section to be Entitled
+ "Endorsements" or to conflict in title with any Invariant Section.
+
+Preserve any Warranty Disclaimers.
+
+
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant. To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled "Endorsements", provided it
+contains nothing but endorsements of your Modified Version by various
+parties--for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text,
+and a passage of up to 25 words as a Back-Cover Text, to the end of the
+list of Cover Texts in the Modified Version. Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or through
+arrangements made by) any one entity. If the Document already includes
+a cover text for the same cover, previously added by you or by
+arrangement made by the same entity you are acting on behalf of, you may
+not add another; but you may replace the old one, on explicit permission
+from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this
+License give permission to use their names for publicity for or to
+assert or imply endorsement of any Modified Version.
+
+
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under
+this License, under the terms defined in section
+4 above for modified versions, provided that you include in the
+combination all of the Invariant Sections of all of the original
+documents, unmodified, and list them all as Invariant Sections of your
+combined work in its license notice, and that you preserve all their
+Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy. If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by adding
+at the end of it, in parentheses, the name of the original author or
+publisher of that section if known, or else a unique number. Make the
+same adjustment to the section titles in the list of Invariant Sections
+in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled
+"History" in the various original documents, forming one section
+Entitled "History"; likewise combine any sections Entitled
+"Acknowledgements", and any sections Entitled "Dedications". You must
+delete all sections Entitled "Endorsements".
+
+
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other
+documents released under this License, and replace the individual copies
+of this License in the various documents with a single copy that is
+included in the collection, provided that you follow the rules of this
+License for verbatim copying of each of the documents in all other
+respects.
+
+You may extract a single document from such a collection, and
+distribute it individually under this License, provided you insert a
+copy of this License into the extracted document, and follow this
+License in all other respects regarding verbatim copying of that
+document.
+
+
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other
+separate and independent documents or works, in or on a volume of a
+storage or distribution medium, is called an "aggregate" if the
+copyright resulting from the compilation is not used to limit the legal
+rights of the compilation's users beyond what the individual works
+permit. When the Document is included an aggregate, this License does
+not apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on covers
+that bracket the Document within the aggregate, or the electronic
+equivalent of covers if the Document is in electronic form. Otherwise
+they must appear on printed covers that bracket the whole
+aggregate.
+
+
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections. You may include a
+translation of this License, and all the license notices in the
+Document, and any Warranty Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers. In case of a disagreement between the
+translation and the original version of this License or a notice or
+disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled "Acknowledgements",
+"Dedications", or "History", the requirement (section 4) to Preserve its
+Title (section 1) will typically require changing the actual
+title.
+
+
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document
+except as expressly provided for under this License. Any other attempt
+to copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License. However,
+parties who have received copies, or rights, from you under this License
+will not have their licenses terminated so long as such parties remain
+in full compliance.
+
+
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions of
+the GNU Free Documentation License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in
+detail to address new problems or concerns. See
+http://www.gnu.org/copyleft/.
+
+Each version of the License is given a distinguishing version
+number. If the Document specifies that a particular numbered version of
+this License "or any later version" applies to it, you have the option
+of following the terms and conditions either of that specified version
+or of any later version that has been published (not as a draft) by the
+Free Software Foundation. If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+
+
+ADDENDUM: How to use this License for
+ your documents
+
+To use this License in a document you have written, include a copy
+of the License in the document and put the following copyright and
+license notices just after the title page:
+
+
+ Copyright (c) YEAR YOUR NAME.
+ Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+ A copy of the license is included in the section entitled "GNU
+ Free Documentation License".
+
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover
+Texts, replace the "with...Texts." line with this:
+
+
+ with the Invariant Sections being LIST THEIR TITLES, with the
+ Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of free
+software license, such as the GNU General Public License, to permit
+their use in free software.
+
+
+
+
+
diff -urN linux-2.5.70-bk10/Documentation/rocket.txt linux-2.5.70-bk11/Documentation/rocket.txt
--- linux-2.5.70-bk10/Documentation/rocket.txt 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk11/Documentation/rocket.txt 2003-06-06 04:38:19.000000000 -0700
@@ -0,0 +1,87 @@
+Comtrol(tm) RocketPort(R)/RocketModem(TM) Series
+Device Driver for the Linux Operating System
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+PRODUCT OVERVIEW
+----------------
+
+This driver provides a loadable kernel driver for the Comtrol RocketPort
+and RocketModem PCI boards. These boards provide, 2, 4, 8, 16, or 32
+high-speed serial ports or modems. This driver supports up to a combination
+of four RocketPort or RocketModems boards in one machine simultaneously.
+This file assumes that you are using the RocketPort driver which is
+integrated into the kernel sources.
+
+The driver can also be installed as an external module using the usual
+"make;make install" routine. This external module driver, obtainable
+from the Comtrol website listed below, is useful for updating the driver
+or installing it into kernels which do not have the driver configured
+into them. Installations instructions for the external module
+are in the included README and HW_INSTALL files.
+
+RocketPort ISA and RocketModem II PCI boards are also supported by this
+driver, but must use the external module driver for configuration reasons.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+INSTALLATION PROCEDURES
+-----------------------
+
+RocketPort/RocketModem PCI cards require no driver configuration, they are
+automatically detected and configured.
+
+The RocketPort driver can be installed as a module (recommended) or built
+into the kernel. This is selected, as for other drivers, through the `make config`
+command from the root of the Linux source tree during the kernel build process.
+
+The RocketPort/RocketModem serial ports installed by this driver are assigned
+device major number 46, and will be named /dev/ttyRx, where x is the port number
+starting at zero (ex. /dev/ttyR0, /devttyR1, ...). If you have multiple cards
+installed in the system, the mapping of port names to serial ports is displayed
+in the system log at /var/log/messages.
+
+If installed as a module, the module must be loaded. This can be done
+manually by entering "modprobe rocket". To have the module loaded automatically
+upon system boot, edit the /etc/modules.conf file and add the line
+"alias char-major-46 rocket".
+
+In order to use the ports, their device names (nodes) must be created with mknod.
+This is only required once, the system will retain the names once created. To
+create the RocketPort/RocketModem device names, use the command
+"mknod /dev/ttyRx c 46 x" where x is the port number starting at zero. For example:
+
+>mknod /dev/ttyR0 c 46 0
+>mknod /dev/ttyR1 c 46 1
+>mknod /dev/ttyR2 c 46 2
+
+The Linux script MAKEDEV will create the first 16 ttyRx device names (nodes) for you:
+
+>/dev/MAKEDEV ttyR
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+REPORTING BUGS
+--------------
+
+For technical support, please provide the following
+information: Driver version, kernel release, distribution of
+kernel, and type of board you are using. Error messages and log
+printouts port configuration details are especially helpful.
+
+USA
+ Phone: (612) 494-4100
+ FAX: (612) 494-4199
+ email: support@comtrol.com
+
+Comtrol Europe
+ Phone: +44 (0) 1 869 323-220
+ FAX: +44 (0) 1 869 323-211
+ email: support@comtrol.co.uk
+
+Web: http://www.comtrol.com
+FTP: ftp.comtrol.com
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+
diff -urN linux-2.5.70-bk10/MAINTAINERS linux-2.5.70-bk11/MAINTAINERS
--- linux-2.5.70-bk10/MAINTAINERS 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/MAINTAINERS 2003-06-06 04:38:19.000000000 -0700
@@ -281,6 +281,13 @@
W: http://linux-atm.sourceforge.net
S: Maintained
+ATMEL WIRELESS DRIVER
+P: Simon Kelley
+M: simon@thekelleys.org.uk
+W: http://www.thekelleys.org.uk/atmel
+W: http://atmelwlandriver.sourceforge.net/
+S: Maintained
+
AX.25 NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
@@ -1524,6 +1531,12 @@
W: http://www.namesys.com
S: Supported
+ROCKETPORT DRIVER
+P: Comtrol Corp.
+M: support@comtrol.com
+W: http://www.comtrol.com
+S: Maintained
+
ROSE NETWORK LAYER
P: Ralf Baechle
M: ralf@linux-mips.org
diff -urN linux-2.5.70-bk10/Makefile linux-2.5.70-bk11/Makefile
--- linux-2.5.70-bk10/Makefile 2003-06-06 04:38:11.000000000 -0700
+++ linux-2.5.70-bk11/Makefile 2003-06-06 04:38:19.000000000 -0700
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 70
-EXTRAVERSION = -bk10
+EXTRAVERSION = -bk11
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff -urN linux-2.5.70-bk10/arch/alpha/kernel/core_marvel.c linux-2.5.70-bk11/arch/alpha/kernel/core_marvel.c
--- linux-2.5.70-bk10/arch/alpha/kernel/core_marvel.c 2003-05-26 18:00:22.000000000 -0700
+++ linux-2.5.70-bk11/arch/alpha/kernel/core_marvel.c 2003-06-06 04:38:19.000000000 -0700
@@ -980,7 +980,7 @@
}
static int
-marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
@@ -988,7 +988,7 @@
}
static int
-marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
struct marvel_agp_aperture *aper = agp->aperture.sysdata;
return iommu_unbind(aper->arena, aper->pg_start + pg_start,
diff -urN linux-2.5.70-bk10/arch/alpha/kernel/core_titan.c linux-2.5.70-bk11/arch/alpha/kernel/core_titan.c
--- linux-2.5.70-bk10/arch/alpha/kernel/core_titan.c 2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk11/arch/alpha/kernel/core_titan.c 2003-06-06 04:38:19.000000000 -0700
@@ -679,7 +679,7 @@
}
static int
-titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_bind(aper->arena, aper->pg_start + pg_start,
@@ -687,7 +687,7 @@
}
static int
-titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, agp_memory *mem)
+titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
struct titan_agp_aperture *aper = agp->aperture.sysdata;
return iommu_unbind(aper->arena, aper->pg_start + pg_start,
diff -urN linux-2.5.70-bk10/arch/alpha/kernel/systbls.S linux-2.5.70-bk11/arch/alpha/kernel/systbls.S
--- linux-2.5.70-bk10/arch/alpha/kernel/systbls.S 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/arch/alpha/kernel/systbls.S 2003-06-06 04:38:19.000000000 -0700
@@ -433,6 +433,15 @@
.quad sys_set_tid_address
.quad sys_restart_syscall
.quad sys_fadvise64
+ .quad sys_timer_create
+ .quad sys_timer_settime /* 415 */
+ .quad sys_timer_gettime
+ .quad sys_timer_getoverrun
+ .quad sys_timer_delete
+ .quad sys_clock_settime
+ .quad sys_clock_gettime /* 420 */
+ .quad sys_clock_getres
+ .quad sys_clock_nanosleep
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
diff -urN linux-2.5.70-bk10/arch/cris/drivers/ethernet.c linux-2.5.70-bk11/arch/cris/drivers/ethernet.c
--- linux-2.5.70-bk10/arch/cris/drivers/ethernet.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/arch/cris/drivers/ethernet.c 2003-06-06 04:38:19.000000000 -0700
@@ -292,37 +292,19 @@
*/
static int __init
-etrax_ethernet_init(struct net_device *dev)
+etrax_ethernet_init(void)
{
- int i;
+ struct net_device *dev;
+ int i, err;
int anOffset = 0;
printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000-2001 Axis Communications AB\n");
- dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
-
- printk("%s initialized\n", dev->name);
-
- /* make Linux aware of the new hardware */
-
- if (!dev) {
- printk(KERN_WARNING "%s: dev == NULL. Should this happen?\n",
- cardname);
- dev = init_etherdev(dev, sizeof(struct net_local));
- if (!dev)
- panic("init_etherdev failed\n");
- }
-
- /* setup generic handlers and stuff in the dev struct */
-
- ether_setup(dev);
-
- /* make room for the local structure containing stats etc */
-
- dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
- if (dev->priv == NULL)
+ dev = alloc_etherdev(sizeof(struct net_local));
+ if (!dev)
return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_local));
+
+ dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
/* now setup our etrax specific stuff */
@@ -340,10 +322,6 @@
dev->do_ioctl = e100_ioctl;
dev->tx_timeout = e100_tx_timeout;
- /* set the default MAC address */
-
- e100_set_mac_address(dev, &default_mac);
-
/* Initialise the list of Etrax DMA-descriptors */
/* Initialise receive descriptors */
@@ -371,6 +349,16 @@
myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+ err = register_netdev(dev);
+ if (err) {
+ kfree(dev);
+ return err;
+ }
+
+ /* set the default MAC address */
+
+ e100_set_mac_address(dev, &default_mac);
+
/* Initialize speed indicator stuff. */
current_speed = 10;
@@ -1349,19 +1337,10 @@
}
}
-static struct net_device dev_etrax_ethernet; /* only got one */
-
static int
etrax_init_module(void)
{
- struct net_device *d = &dev_etrax_ethernet;
-
- d->init = etrax_ethernet_init;
-
- if (register_netdev(d) == 0)
- return 0;
- else
- return -ENODEV;
+ return etrax_ethernet_init();
}
module_init(etrax_init_module);
diff -urN linux-2.5.70-bk10/arch/cris/drivers/lpslave/e100lpslavenet.c linux-2.5.70-bk11/arch/cris/drivers/lpslave/e100lpslavenet.c
--- linux-2.5.70-bk10/arch/cris/drivers/lpslave/e100lpslavenet.c 2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk11/arch/cris/drivers/lpslave/e100lpslavenet.c 2003-06-06 04:38:19.000000000 -0700
@@ -162,37 +162,19 @@
* (detachable devices only).
*/
static int __init
-etrax_ethernet_lpslave_init(struct net_device *dev)
+etrax_ethernet_lpslave_init(void)
{
- int i;
+ struct net_device *dev;
+ int i, err;
int anOffset = 0;
printk("Etrax/100 lpslave ethernet driver v0.3, (c) 1999 Axis Communications AB\n");
- dev->base_addr = 2;
-
- printk("%s initialized\n", dev->name);
-
- /* make Linux aware of the new hardware */
-
- if (!dev) {
- printk(KERN_WARNING "%s: dev == NULL. Should this happen?\n",
- cardname);
- dev = init_etherdev(dev, sizeof(struct net_local));
- if (!dev)
- panic("init_etherdev failed\n");
- }
-
- /* setup generic handlers and stuff in the dev struct */
-
- ether_setup(dev);
-
- /* make room for the local structure containing stats etc */
-
- dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
- if (dev->priv == NULL)
+ dev = alloc_etherdev(sizeof(struct net_lock));
+ if (!dev)
return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_local));
+
+ dev->base_addr = 2;
/* now setup our etrax specific stuff */
@@ -242,7 +224,11 @@
TxDescList[0].buf = virt_to_phys(&host_command);
TxDescList[0].next = virt_to_phys(&TxDescList[1]);
- return 0;
+ err = register_netdev(dev);
+ if (err)
+ kfree(dev);
+
+ return err;
}
/* set MAC address of the interface. called from the core after a
@@ -1017,19 +1003,10 @@
}
#endif /* ETHDEBUG */
-static struct net_device dev_etrax_slave_ethernet;
-
static int
etrax_init_module(void)
{
- struct net_device *d = &dev_etrax_slave_ethernet;
-
- d->init = etrax_ethernet_lpslave_init;
-
- if(register_netdev(d) == 0)
- return 0;
- else
- return -ENODEV;
+ return etrax_ethernet_lpslave_init();
}
module_init(etrax_init_module);
diff -urN linux-2.5.70-bk10/arch/ia64/hp/sim/simeth.c linux-2.5.70-bk11/arch/ia64/hp/sim/simeth.c
--- linux-2.5.70-bk10/arch/ia64/hp/sim/simeth.c 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/arch/ia64/hp/sim/simeth.c 2003-06-06 04:38:19.000000000 -0700
@@ -191,7 +191,7 @@
unsigned char mac_addr[ETH_ALEN];
struct simeth_local *local;
struct net_device *dev;
- int fd, i;
+ int fd, i, err;
/*
* XXX Fix me
@@ -207,22 +207,12 @@
if (fd == -1)
return -ENODEV;
- dev = init_etherdev(NULL, sizeof(struct simeth_local));
+ dev = alloc_etherdev(sizeof(struct simeth_local));
if (!dev)
return -ENOMEM;
memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr));
- dev->irq = ia64_alloc_vector();
-
- /*
- * attach the interrupt in the simulator, this does enable interrupts
- * until a netdev_attach() is called
- */
- netdev_connect(dev->irq);
-
- memset(dev->priv, 0, sizeof(struct simeth_local));
-
local = dev->priv;
local->simfd = fd; /* keep track of underlying file descriptor */
@@ -232,8 +222,19 @@
dev->get_stats = simeth_get_stats;
dev->set_multicast_list = set_multicast_list; /* no yet used */
- /* Fill in the fields of the device structure with ethernet-generic values. */
- ether_setup(dev);
+ err = register_netdev(dev);
+ if (dev) {
+ kfree(dev);
+ return err;
+ }
+
+ dev->irq = ia64_alloc_vector();
+
+ /*
+ * attach the interrupt in the simulator, this does enable interrupts
+ * until a netdev_attach() is called
+ */
+ netdev_connect(dev->irq);
printk(KERN_INFO "%s: hosteth=%s simfd=%d, HwAddr",
dev->name, simeth_device, local->simfd);
@@ -242,7 +243,7 @@
}
printk(", IRQ %d\n", dev->irq);
- return 0;
+ return 0;
}
/*
diff -urN linux-2.5.70-bk10/arch/m68k/atari/hades-pci.c linux-2.5.70-bk11/arch/m68k/atari/hades-pci.c
--- linux-2.5.70-bk10/arch/m68k/atari/hades-pci.c 2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk11/arch/m68k/atari/hades-pci.c 2003-06-06 04:38:20.000000000 -0700
@@ -297,14 +297,14 @@
IRQ_TT_MFP_SCC, /* Slot 2. */
IRQ_TT_MFP_SCSIDMA /* Slot 3. */
};
- struct pci_dev *dev;
+ struct pci_dev *dev = NULL;
unsigned char slot;
/*
* Go through all devices, fixing up irqs as we see fit:
*/
- for (dev = pci_devices; dev; dev = dev->next)
+ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
{
if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
{
diff -urN linux-2.5.70-bk10/arch/ppc/8260_io/enet.c linux-2.5.70-bk11/arch/ppc/8260_io/enet.c
--- linux-2.5.70-bk10/arch/ppc/8260_io/enet.c 2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/8260_io/enet.c 2003-06-06 04:38:20.000000000 -0700
@@ -630,19 +630,15 @@
bd = (bd_t *)__res;
- /* Allocate some private information.
+ /* Create an Ethernet device instance.
*/
- cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
- if (cep == NULL)
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
return -ENOMEM;
- __clear_user(cep,sizeof(*cep));
+ cep = dev->priv;
spin_lock_init(&cep->lock);
- /* Create an Ethernet device instance.
- */
- dev = init_etherdev(0, 0);
-
/* Get pointer to SCC area in parameter RAM.
*/
ep = (scc_enet_t *)(&immap->im_dprambase[PROFF_ENET]);
@@ -771,6 +767,7 @@
/* Allocate a page.
*/
mem_addr = __get_free_page(GFP_KERNEL);
+ /* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
@@ -808,6 +805,7 @@
/* Install our interrupt handler.
*/
request_irq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+ /* BUG: no check for failure */
/* Set GSMR_H to enable all normal operating modes.
* Set GSMR_L to enable Ethernet to MC68160.
@@ -837,7 +835,6 @@
io->iop_pdatc |= PC_EST8260_ENET_NOTFD;
dev->base_addr = (unsigned long)ep;
- dev->priv = cep;
/* The CPM Ethernet specific entries in the device structure. */
dev->open = scc_enet_open;
@@ -852,6 +849,12 @@
*/
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ err = register_netdev(dev);
+ if (err) {
+ kfree(dev);
+ return err;
+ }
+
printk("%s: SCC ENET Version 0.1, ", dev->name);
for (i=0; i<5; i++)
printk("%02x:", dev->dev_addr[i]);
diff -urN linux-2.5.70-bk10/arch/ppc/8260_io/fcc_enet.c linux-2.5.70-bk11/arch/ppc/8260_io/fcc_enet.c
--- linux-2.5.70-bk10/arch/ppc/8260_io/fcc_enet.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/8260_io/fcc_enet.c 2003-06-06 04:38:20.000000000 -0700
@@ -1328,7 +1328,7 @@
struct net_device *dev;
struct fcc_enet_private *cep;
fcc_info_t *fip;
- int i, np;
+ int i, np, err;
volatile immap_t *immap;
volatile iop8260_t *io;
@@ -1339,23 +1339,16 @@
fip = fcc_ports;
while (np-- > 0) {
-
- /* Allocate some private information.
+ /* Create an Ethernet device instance.
*/
- cep = (struct fcc_enet_private *)
- kmalloc(sizeof(*cep), GFP_KERNEL);
- if (cep == NULL)
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
return -ENOMEM;
- __clear_user(cep,sizeof(*cep));
+ cep = dev->priv;
spin_lock_init(&cep->lock);
cep->fip = fip;
- /* Create an Ethernet device instance.
- */
- dev = init_etherdev(0, 0);
- dev->priv = cep;
-
init_fcc_shutdown(fip, cep, immap);
init_fcc_ioports(fip, io, immap);
init_fcc_param(fip, dev, immap);
@@ -1376,6 +1369,12 @@
init_fcc_startup(fip, dev);
+ err = register_netdev(dev);
+ if (err) {
+ kfree(dev);
+ return err;
+ }
+
printk("%s: FCC ENET Version 0.3, ", dev->name);
for (i=0; i<5; i++)
printk("%02x:", dev->dev_addr[i]);
diff -urN linux-2.5.70-bk10/arch/ppc/8xx_io/enet.c linux-2.5.70-bk11/arch/ppc/8xx_io/enet.c
--- linux-2.5.70-bk10/arch/ppc/8xx_io/enet.c 2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/8xx_io/enet.c 2003-06-06 04:38:20.000000000 -0700
@@ -643,7 +643,7 @@
{
struct net_device *dev;
struct scc_enet_private *cep;
- int i, j, k;
+ int i, j, k, err;
unsigned char *eap, *ba;
dma_addr_t mem_addr;
bd_t *bd;
@@ -659,19 +659,13 @@
bd = (bd_t *)__res;
- /* Allocate some private information.
- */
- cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
- if (cep == NULL)
+ dev = alloc_etherdev(sizeof(*cep));
+ if (!dev)
return -ENOMEM;
- __clear_user(cep,sizeof(*cep));
+ cep = dev->priv;
spin_lock_init(&cep->lock);
- /* Create an Ethernet device instance.
- */
- dev = init_etherdev(0, 0);
-
/* Get pointer to SCC area in parameter RAM.
*/
ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_ENET]);
@@ -841,6 +835,7 @@
/* Allocate a page.
*/
ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+ /* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
@@ -939,7 +934,6 @@
#endif
dev->base_addr = (unsigned long)ep;
- dev->priv = cep;
#if 0
dev->name = "CPM_ENET";
#endif
@@ -953,6 +947,12 @@
dev->get_stats = scc_enet_get_stats;
dev->set_multicast_list = set_multicast_list;
+ err = register_netdev(dev);
+ if (err) {
+ kfree(dev);
+ return err;
+ }
+
/* And last, enable the transmit and receive processing.
*/
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
diff -urN linux-2.5.70-bk10/arch/ppc/8xx_io/fec.c linux-2.5.70-bk11/arch/ppc/8xx_io/fec.c
--- linux-2.5.70-bk10/arch/ppc/8xx_io/fec.c 2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/8xx_io/fec.c 2003-06-06 04:38:20.000000000 -0700
@@ -1570,7 +1570,7 @@
{
struct net_device *dev;
struct fec_enet_private *fep;
- int i, j, k;
+ int i, j, k, err;
unsigned char *eap, *iap, *ba;
unsigned long mem_addr;
volatile cbd_t *bdp;
@@ -1586,17 +1586,11 @@
bd = (bd_t *)__res;
- /* Allocate some private information.
- */
- fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
- if (fep == NULL)
+ dev = alloc_etherdev(sizeof(*fep));
+ if (!dev)
return -ENOMEM;
- __clear_user(fep,sizeof(*fep));
-
- /* Create an Ethernet device instance.
- */
- dev = init_etherdev(0, 0);
+ fep = dev->priv;
fecp = &(immap->im_cpm.cp_fec);
@@ -1661,6 +1655,7 @@
/* Allocate a page.
*/
ba = (unsigned char *)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &mem_addr);
+ /* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
@@ -1715,7 +1710,6 @@
#endif
dev->base_addr = (unsigned long)fecp;
- dev->priv = fep;
/* The FEC Ethernet specific entries in the device structure. */
dev->open = fec_enet_open;
@@ -1752,6 +1746,12 @@
fecp->fec_mii_speed = 0; /* turn off MDIO */
#endif /* CONFIG_USE_MDIO */
+ err = register_netdev(dev);
+ if (err) {
+ kfree(dev);
+ return err;
+ }
+
printk ("%s: FEC ENET Version 0.2, FEC irq %d"
#ifdef PHY_INTERRUPT
", MII irq %d"
diff -urN linux-2.5.70-bk10/arch/ppc/Kconfig linux-2.5.70-bk11/arch/ppc/Kconfig
--- linux-2.5.70-bk10/arch/ppc/Kconfig 2003-05-26 18:01:00.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/Kconfig 2003-06-06 04:38:20.000000000 -0700
@@ -97,32 +97,6 @@
depends on POWER3
default y
-config ALL_PPC
- bool
- depends on ALL_PPC_CH || POWER3
- default y
- ---help---
- Linux currently supports several different kinds of PowerPC-based
- machines: Apple Power Macintoshes and clones (such as the Motorola
- Starmax series), PReP (PowerPC Reference Platform) machines (such
- as the Motorola PowerStacks, Motorola cPCI/VME embedded systems,
- and some IBM RS/6000 systems), CHRP (Common Hardware Reference
- Platform) machines (including all of the recent IBM RS/6000 and
- pSeries machines), and several embedded PowerPC systems containing
- 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
- default option is to build a kernel which works on the first three.
-
- Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or
- pSeries machine, a Power Macintosh (including iMacs, iBooks and
- Powerbooks), or a PReP machine.
-
- Select Gemini if configuring for a Synergy Microsystems' Gemini
- series Single Board Computer. More information is available at:
- .
-
- Select APUS if configuring for a PowerUP Amiga. More information is
- available at: .
-
config PPC_STD_MMU
bool
depends on 6xx || POWER3
@@ -424,12 +398,34 @@
bool
depends on 8xx || 8260
default y
+
choice
prompt "Machine Type"
- depends on 6xx && !8260
- default ALL_PPC_CH
+ depends on (6xx || POWER3) && !8260
+ default PPC_MULTIPLATFORM
+ ---help---
+ Linux currently supports several different kinds of PowerPC-based
+ machines: Apple Power Macintoshes and clones (such as the Motorola
+ Starmax series), PReP (PowerPC Reference Platform) machines (such
+ as the Motorola PowerStacks, Motorola cPCI/VME embedded systems,
+ and some IBM RS/6000 systems), CHRP (Common Hardware Reference
+ Platform) machines (including all of the recent IBM RS/6000 and
+ pSeries machines), and several embedded PowerPC systems containing
+ 4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
+ default option is to build a kernel which works on the first three.
-config ALL_PPC_CH
+ Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or
+ pSeries machine, a Power Macintosh (including iMacs, iBooks and
+ Powerbooks), or a PReP machine.
+
+ Select Gemini if configuring for a Synergy Microsystems' Gemini
+ series Single Board Computer. More information is available at:
+ .
+
+ Select APUS if configuring for a PowerUP Amiga. More information is
+ available at: .
+
+config PPC_MULTIPLATFORM
bool "CHRP/PowerMac/PReP"
config APUS
@@ -499,6 +495,26 @@
endchoice
+config PPC_CHRP
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_PMAC
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_PREP
+ bool
+ depends on PPC_MULTIPLATFORM
+ default y
+
+config PPC_OF
+ bool
+ depends on PPC_PMAC || PPC_CHRP
+ default y
+
config SANDPOINT_X3
bool "Sandpoint X3"
depends on SANDPOINT
@@ -721,7 +737,7 @@
config ISA
bool "Support for ISA-bus hardware"
- depends on ALL_PPC
+ depends on PREP || CHRP
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -851,7 +867,7 @@
config PPC601_SYNC_FIX
bool "Workarounds for PPC601 bugs"
- depends on ALL_PPC && !POWER3
+ depends on 6xx && !POWER3
help
Some versions of the PPC601 (the first PowerPC chip) have bugs which
mean that extra synchronization instructions are required near
@@ -865,7 +881,7 @@
config PROC_DEVICETREE
bool "Support for Open Firmware device tree in /proc"
- depends on ALL_PPC && PROC_FS
+ depends on PPC_OF && PROC_FS
help
This option adds a device-tree directory under /proc which contains
an image of the device tree that the kernel copies from Open
@@ -873,7 +889,7 @@
config PPC_RTAS
bool "Support for RTAS (RunTime Abstraction Services) in /proc"
- depends on ALL_PPC && PROC_FS
+ depends on PPC_OF && PROC_FS
---help---
When you use this option, you will be able to use RTAS from
userspace.
@@ -906,7 +922,7 @@
config PREP_RESIDUAL
bool "Support for PReP Residual Data"
- depends on ALL_PPC
+ depends on PPC_PREP
help
Some PReP systems have residual data passed to the kernel by the
firmware. This allows detection of memory size, devices present and
@@ -927,7 +943,7 @@
config PPCBUG_NVRAM
bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
- default y if ALL_PPC
+ default y if PPC_PREP
config CMDLINE_BOOL
bool "Default bootloader kernel arguments"
@@ -1156,7 +1172,7 @@
config BOOT_LOAD_BOOL
bool "Set the boot link/load address"
- depends on ADVANCED_OPTIONS && !ALL_PPC
+ depends on ADVANCED_OPTIONS && !PPC_MULTIPLATFORM
help
This option allows you to set the initial load address of the zImage
or zImage.initrd file. This can be useful if you are on a board
@@ -1292,7 +1308,7 @@
# we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU
config ADB_CUDA
bool "Support for CUDA based PowerMacs"
- depends on ALL_PPC
+ depends on PPC_PMAC
help
This provides support for CUDA based Power Macintosh systems. This
includes most OldWorld PowerMacs, the first generation iMacs, the
@@ -1304,7 +1320,7 @@
config ADB_PMU
bool "Support for PMU based PowerMacs"
- depends on ALL_PPC
+ depends on PPC_PMAC
help
On PowerBooks, iBooks, and recent iMacs and Power Macintoshes, the
PMU is an embedded microprocessor whose primary function is to
@@ -1336,7 +1352,7 @@
config PM
bool
- depends on ALL_PPC && ADB_PMU && PMAC_PBOOK
+ depends on PPC_PMAC && ADB_PMU && PMAC_PBOOK
default y
config PMAC_APM_EMU
@@ -1357,14 +1373,14 @@
config MAC_FLOPPY
bool "Support for PowerMac floppy"
- depends on ALL_PPC
+ depends on PPC_PMAC
help
If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple)
floppy controller, say Y here. Most commonly found in PowerMacs.
config MAC_SERIAL
tristate "Support for PowerMac serial ports"
- depends on ALL_PPC
+ depends on PPC_PMAC
help
If you have Macintosh style serial ports (8 pin mini-DIN), say Y
here. If you also have regular serial ports and enable the driver
@@ -1372,11 +1388,11 @@
config SERIAL_CONSOLE
bool "Support for console on serial port"
- depends on ALL_PPC && MAC_SERIAL=y
+ depends on PPC_PMAC && MAC_SERIAL=y
config ADB
bool "Apple Desktop Bus (ADB) support"
- depends on ALL_PPC
+ depends on PPC_PMAC
help
Apple Desktop Bus (ADB) support is for support of devices which
are connected to an ADB port. ADB devices tend to have 4 pins.
@@ -1610,7 +1626,7 @@
config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
- depends on ALL_PPC
+ depends PPC_OF
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires either BootX or Open Firmware.
diff -urN linux-2.5.70-bk10/arch/ppc/boot/Makefile linux-2.5.70-bk11/arch/ppc/boot/Makefile
--- linux-2.5.70-bk10/arch/ppc/boot/Makefile 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/boot/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -16,9 +16,10 @@
BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
bootdir-y := simple
-bootdir-$(CONFIG_ALL_PPC) := openfirmware prep
+bootdir-$(CONFIG_PPC_OF) := openfirmware
+bootdir-$(CONFIG_PPC_PREP) += prep
subdir-y := lib/ common/ images/
-subdir-$(CONFIG_ALL_PPC) += of1275/
+subdir-$(CONFIG_PPC_OF) += of1275/
# for cleaning
subdir- += simple/ openfirmware/ prep/
diff -urN linux-2.5.70-bk10/arch/ppc/boot/common/Makefile linux-2.5.70-bk11/arch/ppc/boot/common/Makefile
--- linux-2.5.70-bk10/arch/ppc/boot/common/Makefile 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/boot/common/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -11,7 +11,7 @@
L_TARGET := lib.a
obj-y := string.o util.o misc-common.o
-obj-$(CONFIG_ALL_PPC) += mpc10x_memory.o
+obj-$(CONFIG_PPC_PREP) += mpc10x_memory.o
obj-$(CONFIG_LOPEC) += mpc10x_memory.o
obj-$(CONFIG_PAL4) += cpc700_memory.o
obj-$(CONFIG_SERIAL_8250_CONSOLE) += ns16550.o
diff -urN linux-2.5.70-bk10/arch/ppc/boot/common/misc-common.c linux-2.5.70-bk11/arch/ppc/boot/common/misc-common.c
--- linux-2.5.70-bk10/arch/ppc/boot/common/misc-common.c 2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/boot/common/misc-common.c 2003-06-06 04:38:20.000000000 -0700
@@ -20,10 +20,10 @@
#include "zlib.h"
#include "nonstdio.h"
-/* If we're on a ALL_PPC, assume we have a keyboard controller
- * Also note, if we're not ALL_PPC, we assume you are a serial
+/* If we're on a PReP, assume we have a keyboard controller
+ * Also note, if we're not PReP, we assume you are a serial
* console - Tom */
-#if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE)
+#if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
extern void cursor(int x, int y);
extern void scroll(void);
extern char *vidmem;
diff -urN linux-2.5.70-bk10/arch/ppc/boot/common/mpc10x_memory.c linux-2.5.70-bk11/arch/ppc/boot/common/mpc10x_memory.c
--- linux-2.5.70-bk10/arch/ppc/boot/common/mpc10x_memory.c 2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/boot/common/mpc10x_memory.c 2003-06-06 04:38:20.000000000 -0700
@@ -50,7 +50,7 @@
/*
* Read the memory controller registers to determine the amount of memory in
* the system. This assumes that the firmware has correctly set up the memory
- * controller registers. On CONFIG_ALL_PPC, we know we are being called
+ * controller registers. On CONFIG_PPC_PREP, we know we are being called
* under a PReP memory map. On all other machines, we assume we are under
* a CHRP memory map.
*/
@@ -62,7 +62,7 @@
int i;
unsigned char bank_enables;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PREP
config_addr = (unsigned int *)MPC10X_MAPA_CNFG_ADDR;
config_data = (unsigned int *)MPC10X_MAPA_CNFG_DATA;
#else
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/entry.S linux-2.5.70-bk11/arch/ppc/kernel/entry.S
--- linux-2.5.70-bk10/arch/ppc/kernel/entry.S 2003-06-06 04:38:11.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/entry.S 2003-06-06 04:38:20.000000000 -0700
@@ -820,7 +820,7 @@
* here so it's easy to add arch-specific sections later.
* -- Cort
*/
-#if defined(CONFIG_ALL_PPC)
+#ifdef CONFIG_PPC_OF
/*
* On CHRP, the Run-Time Abstraction Services (RTAS) have to be
* called with the MMU off.
@@ -865,4 +865,4 @@
twi 31,0,0
/* XXX load up BATs and panic */
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_OF */
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/head.S linux-2.5.70-bk11/arch/ppc/kernel/head.S
--- linux-2.5.70-bk10/arch/ppc/kernel/head.S 2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/head.S 2003-06-06 04:38:20.000000000 -0700
@@ -363,21 +363,21 @@
mtspr SPRG0,r10
mtspr SPRG1,r11
mfcr r10
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_CHRP
mfspr r11,SPRG2
cmpwi 0,r11,0
bne 7f
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_CHRP */
EXCEPTION_PROLOG_1
7: EXCEPTION_PROLOG_2
addi r3,r1,STACK_FRAME_OVERHEAD
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_CHRP
mfspr r4,SPRG2
cmpwi cr1,r4,0
bne cr1,1f
#endif
EXC_XFER_STD(0x200, MachineCheckException)
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_CHRP
1: b machine_check_in_rtas
#endif
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/pci.c linux-2.5.70-bk11/arch/ppc/kernel/pci.c
--- linux-2.5.70-bk10/arch/ppc/kernel/pci.c 2003-06-06 04:38:11.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/pci.c 2003-06-06 04:38:20.000000000 -0700
@@ -45,8 +45,10 @@
static int reparent_resources(struct resource *parent, struct resource *res);
static void fixup_rev1_53c810(struct pci_dev* dev);
static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
static void pcibios_fixup_cardbus(struct pci_dev* dev);
+#endif
+#ifdef CONFIG_PPC_OF
static u8* pci_to_OF_bus_map;
#endif
@@ -65,10 +67,10 @@
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810 },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64},
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_TI, PCI_ANY_ID, pcibios_fixup_cardbus },
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
{ 0 }
};
@@ -153,7 +155,7 @@
ppc_md.pcibios_fixup_resources(dev);
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
static void
pcibios_fixup_cardbus(struct pci_dev* dev)
{
@@ -188,7 +190,7 @@
pci_write_config_byte(dev, 0x92, val & ~0x06);
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
@@ -676,7 +678,7 @@
return hose;
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
/*
* Functions below are used on OpenFirmware machines.
*/
@@ -1026,7 +1028,9 @@
prom_add_property(find_path_device("/"), of_prop);
}
}
+#endif /* CONFIG_PPC_OF */
+#ifdef CONFIG_PPC_PMAC
/*
* This set of routines checks for PCI<->PCI bridges that have closed
* IO resources and have child devices. It tries to re-open an IO
@@ -1235,7 +1239,7 @@
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
static int __init
pcibios_init(void)
@@ -1277,9 +1281,9 @@
pcibios_allocate_bus_resources(&pci_root_buses);
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
pcibios_assign_resources();
/* Call machine dependent post-init code */
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/ppc_ksyms.c linux-2.5.70-bk11/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.5.70-bk10/arch/ppc/kernel/ppc_ksyms.c 2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/ppc_ksyms.c 2003-06-06 04:38:20.000000000 -0700
@@ -94,7 +94,7 @@
EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
EXPORT_SYMBOL_NOVERS(DMA_MODE_READ);
EXPORT_SYMBOL(DMA_MODE_WRITE);
-#if defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_PPC_PREP)
EXPORT_SYMBOL(_prep_type);
EXPORT_SYMBOL(ucSystemType);
#endif
@@ -238,9 +238,14 @@
EXPORT_SYMBOL(set_backlight_enable);
EXPORT_SYMBOL(register_backlight_controller);
#endif /* CONFIG_PMAC_BACKLIGHT */
-#if defined(CONFIG_ALL_PPC)
+#ifdef CONFIG_PPC_MULTIPLATFORM
EXPORT_SYMBOL(_machine);
+#endif
+#ifdef CONFIG_PPC_PMAC
EXPORT_SYMBOL_NOVERS(sys_ctrler);
+EXPORT_SYMBOL(pmac_newworld);
+#endif
+#ifdef CONFIG_PPC_OF
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
EXPORT_SYMBOL(find_compatible_devices);
@@ -254,12 +259,11 @@
EXPORT_SYMBOL(pci_busdev_to_OF_node);
EXPORT_SYMBOL(pci_device_to_OF_node);
EXPORT_SYMBOL(pci_device_from_OF_node);
-EXPORT_SYMBOL(pmac_newworld);
-#endif /* defined(CONFIG_ALL_PPC) */
+#endif /* CONFIG_PPC_OF */
#if defined(CONFIG_BOOTX_TEXT)
EXPORT_SYMBOL(btext_update_display);
#endif
-#if defined(CONFIG_SCSI) && defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC)
EXPORT_SYMBOL(note_scsi_host);
#endif
#ifdef CONFIG_VT
@@ -337,7 +341,7 @@
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_4xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_40x)
EXPORT_SYMBOL(__res);
#endif
#if defined(CONFIG_8xx)
@@ -354,7 +358,7 @@
EXPORT_SYMBOL(intercept_table);
#endif
EXPORT_SYMBOL(cur_cpu_spec);
-#if defined(CONFIG_ALL_PPC)
+#ifdef CONFIG_PPC_PMAC
extern unsigned long agp_special_page;
EXPORT_SYMBOL_NOVERS(agp_special_page);
-#endif /* defined(CONFIG_ALL_PPC) */
+#endif
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/setup.c linux-2.5.70-bk11/arch/ppc/kernel/setup.c
--- linux-2.5.70-bk10/arch/ppc/kernel/setup.c 2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/setup.c 2003-06-06 04:38:20.000000000 -0700
@@ -68,7 +68,7 @@
unsigned long ISA_DMA_THRESHOLD;
unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
int _machine = 0;
extern void prep_init(unsigned long r3, unsigned long r4,
@@ -77,7 +77,7 @@
unsigned long r5, unsigned long r6, unsigned long r7);
extern void chrp_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY = 0x54;
@@ -286,7 +286,7 @@
identify_cpu(offset, 0);
do_cpu_ftr_fixups(offset);
-#if defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_PPC_MULTIPLATFORM)
reloc_got2(offset);
/* If we came here from BootX, clear the screen,
@@ -308,7 +308,7 @@
return phys;
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
/*
* Assume here that all clock rates are the same in a
* smp system. -- Cort
@@ -351,9 +351,11 @@
}
}
}
+#endif
+#ifdef CONFIG_PPC_MULTIPLATFORM
/*
- * The ALL_PPC version of platform_init...
+ * The PPC_MULTIPLATFORM version of platform_init...
*/
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -459,7 +461,7 @@
break;
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
struct bi_record *find_bootinfo(void)
{
@@ -501,11 +503,11 @@
initrd_end = data[0] + data[1] + KERNELBASE;
break;
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
case BI_MACHTYPE:
_machine = data[0];
break;
-#endif /* CONFIG_ALL_PPC */
+#endif
case BI_MEMSIZE:
boot_mem_size = data[0];
break;
@@ -596,13 +598,13 @@
/* so udelay does something sensible, assume <= 1000 bogomips */
loops_per_jiffy = 500000000 / HZ;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
/* This could be called "early setup arch", it must be done
* now because xmon need it
*/
if (_machine == _MACH_Pmac)
pmac_feature_init(); /* New cool way */
-#endif /* CONFIG_ALL_PPC */
+#endif
#ifdef CONFIG_XMON
xmon_map_scc();
diff -urN linux-2.5.70-bk10/arch/ppc/kernel/traps.c linux-2.5.70-bk11/arch/ppc/kernel/traps.c
--- linux-2.5.70-bk10/arch/ppc/kernel/traps.c 2003-06-06 04:38:11.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/kernel/traps.c 2003-06-06 04:38:20.000000000 -0700
@@ -117,7 +117,7 @@
*/
static inline int check_io_access(struct pt_regs *regs)
{
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
@@ -150,7 +150,7 @@
return 1;
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
return 0;
}
diff -urN linux-2.5.70-bk10/arch/ppc/mm/init.c linux-2.5.70-bk11/arch/ppc/mm/init.c
--- linux-2.5.70-bk10/arch/ppc/mm/init.c 2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/mm/init.c 2003-06-06 04:38:20.000000000 -0700
@@ -64,7 +64,7 @@
int mem_init_done;
int init_bootmem_done;
int boot_mapsize;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
unsigned long agp_special_page;
#endif
@@ -411,16 +411,18 @@
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#if defined(CONFIG_ALL_PPC)
+#ifdef CONFIG_PPC_OF
/* mark the RTAS pages as reserved */
if ( rtas_data )
for (addr = (ulong)__va(rtas_data);
addr < PAGE_ALIGN((ulong)__va(rtas_data)+rtas_size) ;
addr += PAGE_SIZE)
SetPageReserved(virt_to_page(addr));
+#endif
+#ifdef CONFIG_PPC_PMAC
if (agp_special_page)
SetPageReserved(virt_to_page(agp_special_page));
-#endif /* defined(CONFIG_ALL_PPC) */
+#endif
if ( sysmap )
for (addr = (unsigned long)sysmap;
addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
@@ -465,10 +467,10 @@
if (sysmap)
printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n",
(unsigned int)sysmap, sysmap_size);
-#if defined(CONFIG_ALL_PPC)
+#ifdef CONFIG_PPC_PMAC
if (agp_special_page)
printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
-#endif /* defined(CONFIG_ALL_PPC) */
+#endif
/* Make sure all our pagetable pages have page->mapping
and page->index set correctly. */
@@ -521,13 +523,15 @@
initrd_end - initrd_start, 1);
}
#endif /* CONFIG_BLK_DEV_INITRD */
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
/* remove the RTAS pages from the available memory */
if (rtas_data)
mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
+#endif
/* remove the sysmap pages from the available memory */
if (sysmap)
mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1);
+#ifdef CONFIG_PPC_PMAC
/* Because of some uninorth weirdness, we need a page of
* memory as high as possible (it must be outside of the
* bus address seen as the AGP aperture). It will be used
@@ -542,7 +546,7 @@
mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0);
agp_special_page = (unsigned long)__va(agp_special_page);
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
}
/* Mark some memory as reserved by removing it from phys_avail. */
diff -urN linux-2.5.70-bk10/arch/ppc/mm/mem_pieces.c linux-2.5.70-bk11/arch/ppc/mm/mem_pieces.c
--- linux-2.5.70-bk10/arch/ppc/mm/mem_pieces.c 2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/mm/mem_pieces.c 2003-06-06 04:38:20.000000000 -0700
@@ -120,7 +120,7 @@
printk("\n");
}
-#if defined(CONFIG_APUS) || defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_APUS) || defined(CONFIG_PPC_OF)
/*
* Add some memory to an array of pieces
*/
@@ -135,7 +135,7 @@
rp->address = start;
rp->size = size;
}
-#endif /* CONFIG_APUS || CONFIG_ALL_PPC */
+#endif /* CONFIG_APUS || CONFIG_PPC_OF */
void __init
mem_pieces_sort(struct mem_pieces *mp)
diff -urN linux-2.5.70-bk10/arch/ppc/platforms/Makefile linux-2.5.70-bk11/arch/ppc/platforms/Makefile
--- linux-2.5.70-bk10/arch/ppc/platforms/Makefile 2003-05-26 18:01:03.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/platforms/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -16,17 +16,15 @@
ifeq ($(CONFIG_APUS),y)
obj-$(CONFIG_PCI) += apus_pci.o
endif
-obj-$(CONFIG_ALL_PPC) += pmac_pic.o pmac_setup.o pmac_time.o \
- pmac_feature.o pmac_pci.o chrp_setup.o\
- chrp_time.o chrp_pci.o prep_pci.o \
- prep_time.o prep_setup.o pmac_sleep.o
-ifeq ($(CONFIG_ALL_PPC),y)
+obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \
+ pmac_feature.o pmac_pci.o pmac_sleep.o
+obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o
+obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_time.o prep_setup.o
+ifeq ($(CONFIG_PPC_PMAC),y)
obj-$(CONFIG_NVRAM) += pmac_nvram.o
-endif
-obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
-ifeq ($(CONFIG_ALL_PPC),y)
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
endif
+obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o
@@ -50,5 +48,6 @@
obj-$(CONFIG_ZX4500) += zx4500_setup.o zx4500_pci.o
ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_ALL_PPC) += pmac_smp.o chrp_smp.o
+obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
+obj-$(CONFIG_PPC_CHRP) += chrp_smp.o
endif
diff -urN linux-2.5.70-bk10/arch/ppc/syslib/Makefile linux-2.5.70-bk11/arch/ppc/syslib/Makefile
--- linux-2.5.70-bk10/arch/ppc/syslib/Makefile 2003-05-26 18:00:22.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/syslib/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -27,8 +27,10 @@
ifeq ($(CONFIG_8xx),y)
obj-$(CONFIG_PCI) += qspan_pci.o i8259.o
endif
-obj-$(CONFIG_ALL_PPC) += prom_init.o prom.o open_pic.o \
- indirect_pci.o i8259.o
+obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
+obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o
+obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o
+obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o
obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_EV64260) += gt64260_common.o gt64260_pic.o \
diff -urN linux-2.5.70-bk10/arch/ppc/xmon/start.c linux-2.5.70-bk11/arch/ppc/xmon/start.c
--- linux-2.5.70-bk10/arch/ppc/xmon/start.c 2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk11/arch/ppc/xmon/start.c 2003-06-06 04:38:20.000000000 -0700
@@ -52,7 +52,7 @@
extern int adb_init(void);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_CHRP
/*
* This looks in the "ranges" property for the primary PCI host bridge
* to find the physical address of the start of PCI/ISA I/O space.
@@ -90,7 +90,7 @@
}
return base;
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_CHRP */
#ifdef CONFIG_MAGIC_SYSRQ
static void sysrq_handle_xmon(int key, struct pt_regs *regs,
@@ -110,7 +110,7 @@
void
xmon_map_scc(void)
{
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_MULTIPLATFORM
volatile unsigned char *base;
if (_machine == _MACH_Pmac) {
diff -urN linux-2.5.70-bk10/arch/sparc/prom/console.c linux-2.5.70-bk11/arch/sparc/prom/console.c
--- linux-2.5.70-bk10/arch/sparc/prom/console.c 2003-05-26 18:00:37.000000000 -0700
+++ linux-2.5.70-bk11/arch/sparc/prom/console.c 2003-06-06 04:38:20.000000000 -0700
@@ -105,7 +105,7 @@
/* Query for input device type */
enum prom_input_device
-prom_query_input_device()
+prom_query_input_device(void)
{
unsigned long flags;
int st_p;
@@ -155,7 +155,7 @@
/* Query for output device type */
enum prom_output_device
-prom_query_output_device()
+prom_query_output_device(void)
{
unsigned long flags;
int st_p;
diff -urN linux-2.5.70-bk10/arch/sparc64/boot/Makefile linux-2.5.70-bk11/arch/sparc64/boot/Makefile
--- linux-2.5.70-bk10/arch/sparc64/boot/Makefile 2003-05-26 18:00:20.000000000 -0700
+++ linux-2.5.70-bk11/arch/sparc64/boot/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -15,7 +15,7 @@
quiet_cmd_piggy = PIGGY $@
cmd_piggy = $(obj)/piggyback $@ System.map $(ROOT_IMG)
quiet_cmd_strip = STRIP $@
- cmd_strip = $(STRIP) -R .comment -R .note vmlinux -o $@
+ cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@
# Actual linking
diff -urN linux-2.5.70-bk10/arch/sparc64/prom/console.c linux-2.5.70-bk11/arch/sparc64/prom/console.c
--- linux-2.5.70-bk10/arch/sparc64/prom/console.c 2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk11/arch/sparc64/prom/console.c 2003-06-06 04:38:20.000000000 -0700
@@ -76,7 +76,7 @@
/* Query for input device type */
enum prom_input_device
-prom_query_input_device()
+prom_query_input_device(void)
{
int st_p;
char propb[64];
@@ -111,7 +111,7 @@
/* Query for output device type */
enum prom_output_device
-prom_query_output_device()
+prom_query_output_device(void)
{
int st_p;
char propb[64];
diff -urN linux-2.5.70-bk10/arch/um/sys-ppc/Makefile linux-2.5.70-bk11/arch/um/sys-ppc/Makefile
--- linux-2.5.70-bk10/arch/um/sys-ppc/Makefile 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/arch/um/sys-ppc/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -6,7 +6,7 @@
OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
ptrace_user.o sysrq.o
-EXTRA_AFLAGS := -DCONFIG_ALL_PPC -I. -I$(TOPDIR)/arch/ppc/kernel
+EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel
all: $(OBJ)
diff -urN linux-2.5.70-bk10/drivers/Makefile linux-2.5.70-bk11/drivers/Makefile
--- linux-2.5.70-bk10/drivers/Makefile 2003-06-06 04:38:11.000000000 -0700
+++ linux-2.5.70-bk11/drivers/Makefile 2003-06-06 04:38:20.000000000 -0700
@@ -31,7 +31,7 @@
obj-$(CONFIG_DIO) += dio/
obj-$(CONFIG_SBUS) += sbus/
obj-$(CONFIG_ZORRO) += zorro/
-obj-$(CONFIG_ALL_PPC) += macintosh/
+obj-$(CONFIG_PPC_PMAC) += macintosh/
obj-$(CONFIG_MAC) += macintosh/
obj-$(CONFIG_SGI) += sgi/
obj-$(CONFIG_PARIDE) += block/paride/
diff -urN linux-2.5.70-bk10/drivers/base/class.c linux-2.5.70-bk11/drivers/base/class.c
--- linux-2.5.70-bk10/drivers/base/class.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/base/class.c 2003-06-06 04:38:20.000000000 -0700
@@ -191,7 +191,7 @@
pr_debug("device class '%s': release.\n",cd->class_id);
if (cls->release)
- cd->release(cd);
+ cls->release(cd);
}
static struct kobj_type ktype_class_device = {
diff -urN linux-2.5.70-bk10/drivers/base/core.c linux-2.5.70-bk11/drivers/base/core.c
--- linux-2.5.70-bk10/drivers/base/core.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/base/core.c 2003-06-06 04:38:20.000000000 -0700
@@ -343,11 +343,40 @@
put_device(dev);
}
+/**
+ * device_for_each_child - device child iterator.
+ * @dev: parent struct device.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over @dev's child devices, and call @fn for each,
+ * passing it @data.
+ *
+ * We check the return of @fn each time. If it returns anything
+ * other than 0, we break out and return that value.
+ */
+int device_for_each_child(struct device * dev, void * data,
+ int (*fn)(struct device *, void *))
+{
+ struct device * child;
+ int error = 0;
+
+ down_read(&devices_subsys.rwsem);
+ list_for_each_entry(child,&dev->children,node) {
+ if((error = fn(child,data)))
+ break;
+ }
+ up_read(&devices_subsys.rwsem);
+ return error;
+}
+
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
}
+EXPORT_SYMBOL(device_for_each_child);
+
EXPORT_SYMBOL(device_initialize);
EXPORT_SYMBOL(device_add);
EXPORT_SYMBOL(device_register);
diff -urN linux-2.5.70-bk10/drivers/block/cciss.c linux-2.5.70-bk11/drivers/block/cciss.c
--- linux-2.5.70-bk10/drivers/block/cciss.c 2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk11/drivers/block/cciss.c 2003-06-06 04:38:20.000000000 -0700
@@ -1961,7 +1961,7 @@
goto queue;
startio:
- __blk_stop_queue(q);
+ blk_stop_queue(q);
start_io(h);
}
@@ -2021,8 +2021,8 @@
/*
* See if we can queue up some more IO
*/
- spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
blk_start_queue(&h->queue);
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return IRQ_HANDLED;
}
/*
diff -urN linux-2.5.70-bk10/drivers/block/ll_rw_blk.c linux-2.5.70-bk11/drivers/block/ll_rw_blk.c
--- linux-2.5.70-bk10/drivers/block/ll_rw_blk.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/block/ll_rw_blk.c 2003-06-06 04:38:20.000000000 -0700
@@ -391,12 +391,6 @@
q->dma_alignment = mask;
}
-void blk_queue_assign_lock(request_queue_t *q, spinlock_t *lock)
-{
- spin_lock_init(lock);
- q->queue_lock = lock;
-}
-
/**
* blk_queue_find_tag - find a request by its tag and queue
*
@@ -1076,30 +1070,12 @@
* blk_start_queue() will clear the stop flag on the queue, and call
* the request_fn for the queue if it was in a stopped state when
* entered. Also see blk_stop_queue(). Must not be called from driver
- * request function due to recursion issues.
+ * request function due to recursion issues. Queue lock must be held.
**/
void blk_start_queue(request_queue_t *q)
{
- if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) {
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- if (!elv_queue_empty(q))
- q->request_fn(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
- }
-}
-
-/**
- * __blk_stop_queue: see blk_stop_queue()
- *
- * Description:
- * Like blk_stop_queue(), but queue_lock must be held
- **/
-void __blk_stop_queue(request_queue_t *q)
-{
- blk_remove_plug(q);
- set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
+ if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+ schedule_work(&q->unplug_work);
}
/**
@@ -1114,15 +1090,12 @@
* or if it simply chooses not to queue more I/O at one point, it can
* call this function to prevent the request_fn from being called until
* the driver has signalled it's ready to go again. This happens by calling
- * blk_start_queue() to restart queue operations.
+ * blk_start_queue() to restart queue operations. Queue lock must be held.
**/
void blk_stop_queue(request_queue_t *q)
{
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- __blk_stop_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_remove_plug(q);
+ set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
}
/**
@@ -2364,7 +2337,6 @@
EXPORT_SYMBOL(blk_nohighio);
EXPORT_SYMBOL(blk_dump_rq_flags);
EXPORT_SYMBOL(submit_bio);
-EXPORT_SYMBOL(blk_queue_assign_lock);
EXPORT_SYMBOL(blk_phys_contig_segment);
EXPORT_SYMBOL(blk_hw_contig_segment);
EXPORT_SYMBOL(blk_get_request);
@@ -2383,7 +2355,6 @@
EXPORT_SYMBOL(blk_start_queue);
EXPORT_SYMBOL(blk_stop_queue);
-EXPORT_SYMBOL(__blk_stop_queue);
EXPORT_SYMBOL(blk_run_queue);
EXPORT_SYMBOL(blk_run_queues);
diff -urN linux-2.5.70-bk10/drivers/char/Kconfig linux-2.5.70-bk11/drivers/char/Kconfig
--- linux-2.5.70-bk10/drivers/char/Kconfig 2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk11/drivers/char/Kconfig 2003-06-06 04:38:20.000000000 -0700
@@ -94,18 +94,21 @@
two modules called ip2 and ip2main.
config ROCKETPORT
- tristate "Comtrol Rocketport support"
+ tristate "Comtrol RocketPort support"
depends on SERIAL_NONSTANDARD
help
- This is a driver for the Comtrol Rocketport cards which provide
- multiple serial ports. You would need something like this to connect
- more than two modems to your Linux box, for instance in order to
- become a dial-in server.
+ This driver supports Comtrol RocketPort and RocketModem PCI boards.
+ These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
+ modems. For information about the RocketPort/RocketModem boards
+ and this driver read .
If you want to compile this driver as a module, say M here and read
. The module will be called
rocket.
+ If you want to compile this driver into the kernel, say Y here. If
+ you don't have a Comtrol RocketPort/RocketModem card installed, say N.
+
config CYCLADES
tristate "Cyclades async mux support"
depends on SERIAL_NONSTANDARD
diff -urN linux-2.5.70-bk10/drivers/char/agp/Kconfig linux-2.5.70-bk11/drivers/char/agp/Kconfig
--- linux-2.5.70-bk10/drivers/char/agp/Kconfig 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/drivers/char/agp/Kconfig 2003-06-06 04:38:20.000000000 -0700
@@ -134,7 +134,7 @@
config AGP_UNINORTH
tristate "Apple UniNorth AGP support"
- depends on AGP && ALL_PPC
+ depends on AGP && PPC_PMAC
help
This option gives you AGP support for Apple machines with a
UniNorth bridge.
diff -urN linux-2.5.70-bk10/drivers/char/rocket.c linux-2.5.70-bk11/drivers/char/rocket.c
--- linux-2.5.70-bk10/drivers/char/rocket.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/char/rocket.c 2003-06-06 04:38:21.000000000 -0700
@@ -1,9 +1,9 @@
/*
- * Rocketport device driver for Linux
+ * RocketPort device driver for Linux
*
- * Written by Theodore Ts'o, 1995, 1996, 1997.
+ * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
*
- * Copyright (C) 1995, 1996, 1997 by Comtrol, Inc.
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -21,60 +21,46 @@
*/
/*
- * Minor number schema:
+ * Kernel Synchronization:
*
- * +-------------------------------+
- * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- * +---+-------+-------+-----------+
- * | C | Board | AIOP | Port # |
- * +---+-------+-------+-----------+
+ * This driver has 2 kernel control paths - exception handlers (calls into the driver
+ * from user mode) and the timer bottom half (tasklet). This is a polled driver, interrupts
+ * are not used.
*
- * C=0 implements normal POSIX tty.
- * C=1 is reserved for the callout device.
+ * Critical data:
+ * - rp_table[], accessed through passed "info" pointers, is a global (static) array of
+ * serial port state information and the xmit_buf circular buffer. Protected by
+ * a per port spinlock.
+ * - xmit_flags[], an array of ints indexed by line (port) number, indicating that there
+ * is data to be transmitted. Protected by atomic bit operations.
+ * - rp_num_ports, int indicating number of open ports, protected by atomic operations.
*
- * Normally, the user won't have to worry about the AIOP; as far as
- * the user is concerned, the lower 5 bits of the minor number address
- * the ports on a particular board (from 0 up to 32).
+ * rp_write() and rp_write_char() functions use a per port semaphore to protect against
+ * simultaneous access to the same port by more than one process.
*/
-/* Kernel includes */
-
+/****** Defines ******/
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "rocket_int.h"
-#ifdef LOCAL_ROCKET_H
-#include "rocket.h"
-#include "version.h"
+#ifdef PCI_NUM_RESOURCES
+#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
#else
-#include
-#define ROCKET_VERSION "1.14c"
-#define ROCKET_DATE "24-Aug-98"
-#endif /* LOCAL_ROCKET_H */
+#define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r])
+#endif
+
+#ifndef VERSION_CODE
+# define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) )
+#endif
+
+#if LINUX_VERSION_CODE < VERSION_CODE(2,2,9) /* No version < 2.2 */
+# error "This kernel is too old: not supported by this file"
+#endif
#define ROCKET_PARANOIA_CHECK
-#define ROCKET_SOFT_FLOW
+#define ROCKET_DISABLE_SIMUSAGE
+#undef ROCKET_SOFT_FLOW
#undef ROCKET_DEBUG_OPEN
#undef ROCKET_DEBUG_INTR
#undef ROCKET_DEBUG_WRITE
@@ -83,7 +69,11 @@
#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
#undef ROCKET_DEBUG_RECEIVE
#undef ROCKET_DEBUG_HANGUP
-
+#undef REV_PCI_ORDER
+#undef ROCKET_DEBUG_IO
+
+#undef CONFIG_DEVFS_FS
+
/* CAUTION!!!!! The TIME_STAT Function relies on the Pentium 64 bit
* register. For various reasons related to 1.2.13, the test for this
@@ -96,46 +86,132 @@
* CPU, there is probably something funny about your CPU.
*/
-#undef TIME_STAT /* For performing timing statistics on driver. */
+#undef TIME_STAT /* For performing timing statistics on driver. */
/* Produces printks, one every TIME_COUNTER loops, eats */
/* some of your CPU time. Good for testing or */
/* other checking, otherwise, leave it undefed */
/* Doug Ledford */
-#define TIME_STAT_CPU 100 /* This needs to be set to your processor speed */
- /* For example, 100Mhz CPU, set this to 100 */
-#define TIME_COUNTER 180000 /* This is how many iterations to run before */
+#define TIME_STAT_CPU 100 /* This needs to be set to your processor speed */
+ /* For example, 100Mhz CPU, set this to 100 */
+#define TIME_COUNTER 180000 /* This is how many iterations to run before */
/* performing the printk statements. */
/* 6000 = 1 minute, 360000 = 1 hour, etc. */
/* Since time_stat is long long, this */
/* Can be really high if you want :) */
-#undef TIME_STAT_VERBOSE /* Undef this if you want a terse log message. */
+#undef TIME_STAT_VERBOSE /* Undef this if you want a terse log message. */
-#define _INLINE_ inline
+#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0)
+#define TTY_DRIVER_NO_DEVFS 0
+#endif
-static struct r_port *rp_table[MAX_RP_PORTS];
-static struct tty_struct *rocket_table[MAX_RP_PORTS];
-static unsigned int xmit_flags[NUM_BOARDS];
+#define POLL_PERIOD HZ/100 /* Polling period .01 seconds (10ms) */
+
+/****** Kernel includes ******/
+
+#ifdef MODVERSIONS
+#if LINUX_VERSION_CODE < VERSION_CODE(2,5,00)
+#include
+#else
+#include
+#endif
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#if LINUX_VERSION_CODE < VERSION_CODE(2,4,0)
+#include
+#else
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/****** RocketPort includes ******/
+
+#include "rocket_int.h"
+#include "rocket.h"
+
+#ifdef LOCAL_ROCKET_H
+#include "version.h"
+#else
+#define ROCKET_VERSION "2.08"
+#define ROCKET_DATE "02-June-2003"
+#endif /* LOCAL_ROCKET_H */
+
+/*
+ * All of the compatibilty code so we can compile serial.c against
+ * older kernels is hidden in rocket_compat.h
+ */
+#if defined(LOCAL_ROCKET_H) || (LINUX_VERSION_CODE < VERSION_CODE(2,3,23))
+#include "rocket_compat.h"
+#endif
+
+/****** RocketPort Local Variables ******/
+
+static struct tty_struct *rocket_table[MAX_RP_PORTS]; /* TTY required variables */
static struct termios *rocket_termios[MAX_RP_PORTS];
static struct termios *rocket_termios_locked[MAX_RP_PORTS];
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void rp_flush_buffer(struct tty_struct *tty);
-
static struct tty_driver rocket_driver;
static int rocket_refcount;
-static int rp_num_ports_open;
+static struct rocket_version driver_version = {
+ ROCKET_VERSION, ROCKET_DATE
+};
+static struct r_port *rp_table[MAX_RP_PORTS]; /* The main repository of serial port state information. */
+static unsigned int xmit_flags[NUM_BOARDS]; /* Bit significant, indicates port had data to transmit. */
+ /* eg. Bit 0 indicates port 0 has xmit data, ... */
+static atomic_t rp_num_ports_open; /* Number of serial ports open */
static struct timer_list rocket_timer;
-unsigned long board1;
-unsigned long board2;
-unsigned long board3;
-unsigned long board4;
-unsigned long controller;
-unsigned long support_low_speed;
-int rp_baud_base = 460800;
+static unsigned long board1; /* ISA addresses, retrieved from rocketport.conf */
+static unsigned long board2;
+static unsigned long board3;
+static unsigned long board4;
+static unsigned long controller;
+static unsigned long support_low_speed;
+static unsigned long modem1;
+static unsigned long modem2;
+static unsigned long modem3;
+static unsigned long modem4;
+static unsigned long pc104_1[8];
+static unsigned long pc104_2[8];
+static unsigned long pc104_3[8];
+static unsigned long pc104_4[8];
+static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
+
+static int rp_baud_base[NUM_BOARDS]; /* Board config info (Someday make a per-board structure) */
static unsigned long rcktpt_io_addr[NUM_BOARDS];
+static int rcktpt_type[NUM_BOARDS];
+static int is_PCI[NUM_BOARDS];
+static rocketModel_t rocketModel[NUM_BOARDS];
static int max_board;
+
#ifdef TIME_STAT
static unsigned long long time_stat;
static unsigned long time_stat_short;
@@ -143,83 +219,140 @@
static unsigned long time_counter;
#endif
+/*
+ * The following arrays define the interrupt bits corresponding to each AIOP.
+ * These bits are different between the ISA and regular PCI boards and the
+ * Universal PCI boards.
+ */
+
+static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
+ AIOP_INTR_BIT_0,
+ AIOP_INTR_BIT_1,
+ AIOP_INTR_BIT_2,
+ AIOP_INTR_BIT_3
+};
+
+static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
+ UPCI_AIOP_INTR_BIT_0,
+ UPCI_AIOP_INTR_BIT_1,
+ UPCI_AIOP_INTR_BIT_2,
+ UPCI_AIOP_INTR_BIT_3
+};
+
+/*
+ * Line number is the ttySIx number (x), the Minor number. We
+ * assign them sequentially, starting at zero. The following
+ * array keeps track of the line number assigned to a given board/aiop/channel.
+ */
+static unsigned char lineNumbers[MAX_RP_PORTS];
+static unsigned long nextLineNumber;
+
+/***** RocketPort Static Prototypes *********/
+static int __init init_ISA(int i, int *reserved_controller);
+static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
+static void rp_flush_buffer(struct tty_struct *tty);
+static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
+static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
+static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
+static void rp_start(struct tty_struct *tty);
+
+#ifdef MODULE
MODULE_AUTHOR("Theodore Ts'o");
-MODULE_DESCRIPTION("Comtrol Rocketport driver");
-MODULE_LICENSE("GPL");
-MODULE_PARM(board1, "i");
+MODULE_DESCRIPTION("Comtrol RocketPort driver");
+MODULE_PARM(board1, "i");
MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
-MODULE_PARM(board2, "i");
+MODULE_PARM(board2, "i");
MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
-MODULE_PARM(board3, "i");
+MODULE_PARM(board3, "i");
MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
-MODULE_PARM(board4, "i");
+MODULE_PARM(board4, "i");
MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
MODULE_PARM(controller, "i");
MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
MODULE_PARM(support_low_speed, "i");
-MODULE_PARM_DESC(support_low_speed, "0 means support 50 baud, 1 means support 460400 baud");
+MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
+MODULE_PARM(modem1, "i");
+MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
+MODULE_PARM(modem2, "i");
+MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
+MODULE_PARM(modem3, "i");
+MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
+MODULE_PARM(modem4, "i");
+MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
+MODULE_PARM(pc104_1, "1-8i");
+MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
+MODULE_PARM(pc104_2, "1-8i");
+MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
+MODULE_PARM(pc104_3, "1-8i");
+MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
+MODULE_PARM(pc104_4, "1-8i");
+MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
+
+int rp_init(void);
+static void rp_cleanup_module(void);
+
+module_init(rp_init);
+module_exit(rp_cleanup_module);
-#include
+#endif
-/*
- * tmp_buf is used as a temporary buffer by rp_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf = 0;
-static DECLARE_MUTEX(tmp_buf_sem);
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("Dual BSD/GPL");
+#endif
-static void rp_start(struct tty_struct *tty);
+/*************************************************************************/
+/* Module code starts here */
static inline int rocket_paranoia_check(struct r_port *info,
- char *name, const char *routine)
+ const char *routine)
{
#ifdef ROCKET_PARANOIA_CHECK
- static const char *badmagic =
- "Warning: bad magic number for rocketport struct %s in %s\n";
if (!info)
return 1;
if (info->magic != RPORT_MAGIC) {
- printk(badmagic, name, routine);
+ printk(KERN_INFO "Warning: bad magic number for rocketport struct in %s\n",
+ routine);
return 1;
}
#endif
return 0;
}
-/*
- * Here begins the interrupt/polling routine for the Rocketport!
+
+/* Serial port receive data function. Called (from timer poll) when an AIOPIC signals
+ * that receive data is present on a serial port. Pulls data from FIFO, moves it into the
+ * tty layer.
*/
-static _INLINE_ void rp_do_receive(struct r_port *info, struct tty_struct *tty,
- CHANNEL_t *cp, unsigned int ChanStatus)
+static void rp_do_receive(struct r_port *info,
+ struct tty_struct *tty,
+ CHANNEL_t * cp, unsigned int ChanStatus)
{
unsigned int CharNStat;
int ToRecv, wRecv, space, count;
- unsigned char *cbuf;
- char *fbuf;
-
- ToRecv= sGetRxCnt(cp);
- space = 2*TTY_FLIPBUF_SIZE;
+ unsigned char *cbuf;
+ char *fbuf;
+
+ ToRecv = sGetRxCnt(cp);
+ space = tty->ldisc.receive_room(tty);
+ if (space > 2 * TTY_FLIPBUF_SIZE)
+ space = 2 * TTY_FLIPBUF_SIZE;
cbuf = tty->flip.char_buf;
fbuf = tty->flip.flag_buf;
count = 0;
#ifdef ROCKET_DEBUG_INTR
- printk("rp_do_receive(%d, %d)...", ToRecv, space);
+ printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
#endif
- if (ToRecv == 0 || (space <= 0))
- return;
-
+
/*
* determine how many we can actually read in. If we can't
* read any in then we have a software overrun condition.
*/
if (ToRecv > space)
ToRecv = space;
-
+
+ if (ToRecv <= 0)
+ return;
+
/*
* if status indicates there are errored characters in the
* FIFO, then enter status mode (a word in FIFO holds
@@ -228,7 +361,7 @@
if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
if (!(ChanStatus & STATMODE)) {
#ifdef ROCKET_DEBUG_RECEIVE
- printk("Entering STATMODE...");
+ printk(KERN_INFO "Entering STATMODE...");
#endif
ChanStatus |= STATMODE;
sEnRxStatusMode(cp);
@@ -242,16 +375,14 @@
*/
if (ChanStatus & STATMODE) {
#ifdef ROCKET_DEBUG_RECEIVE
- printk("Ignore %x, read %x...", info->ignore_status_mask,
+ printk(KERN_INFO "Ignore %x, read %x...", info->ignore_status_mask,
info->read_status_mask);
#endif
while (ToRecv) {
- CharNStat= sInW(sGetTxRxDataIO(cp));
-
+ CharNStat = sInW(sGetTxRxDataIO(cp));
#ifdef ROCKET_DEBUG_RECEIVE
- printk("%x...", CharNStat);
+ printk(KERN_INFO "%x...", CharNStat);
#endif
-
if (CharNStat & STMBREAKH)
CharNStat &= ~(STMFRAMEH | STMPARITYH);
if (CharNStat & info->ignore_status_mask) {
@@ -259,18 +390,14 @@
continue;
}
CharNStat &= info->read_status_mask;
- if (CharNStat & STMBREAKH) {
+ if (CharNStat & STMBREAKH)
*fbuf++ = TTY_BREAK;
-#if 0
- if (info->flags & ROCKET_SAK)
- do_SAK(tty);
-#endif
- } else if (CharNStat & STMPARITYH)
+ else if (CharNStat & STMPARITYH)
*fbuf++ = TTY_PARITY;
else if (CharNStat & STMFRAMEH)
*fbuf++ = TTY_FRAME;
else if (CharNStat & STMRCVROVRH)
- *fbuf++ =TTY_OVERRUN;
+ *fbuf++ = TTY_OVERRUN;
else
*fbuf++ = 0;
*cbuf++ = CharNStat & 0xff;
@@ -284,7 +411,7 @@
*/
if (sGetRxCnt(cp) == 0) {
#ifdef ROCKET_DEBUG_RECEIVE
- printk("Status mode off.\n");
+ printk(KERN_INFO "Status mode off.\n");
#endif
sDisRxStatusMode(cp);
}
@@ -294,86 +421,93 @@
* characters at time by doing repeated word IO
* transfer.
*/
- wRecv= ToRecv >> 1;
+ wRecv = ToRecv >> 1;
if (wRecv)
- sInStrW(sGetTxRxDataIO(cp), cbuf,
- wRecv);
+ sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
if (ToRecv & 1)
- cbuf[ToRecv-1] = sInB(sGetTxRxDataIO(cp));
+ cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
memset(fbuf, 0, ToRecv);
cbuf += ToRecv;
fbuf += ToRecv;
count += ToRecv;
}
- tty->ldisc.receive_buf(tty, tty->flip.char_buf,
- tty->flip.flag_buf, count);
+ /* Push the data up to the tty layer */
+ tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
}
/*
- * This routine is called when a transmit interrupt is found. It's
- * responsible for pushing data found in the transmit buffer out to
- * the serial card.
+ * Serial port transmit data function. Called from the timer polling loop as a
+ * result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
+ * to be sent out the serial port. Data is buffered in rp_table[line].xmit_buf, it is
+ * moved to the port's xmit FIFO. *info is critical data, protected by spinlocks.
*/
-static _INLINE_ void rp_do_transmit(struct r_port *info)
+static void rp_do_transmit(struct r_port *info)
{
- int c;
+ int c;
CHANNEL_t *cp = &info->channel;
struct tty_struct *tty;
-
+ unsigned long flags;
+
#ifdef ROCKET_DEBUG_INTR
- printk("rp_do_transmit ");
+ printk(KERN_INFO "rp_do_transmit ");
#endif
if (!info)
return;
if (!info->tty) {
- printk("rp: WARNING rp_do_transmit called with info->tty==NULL\n");
- xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
+ printk(KERN_INFO "rp: WARNING rp_do_transmit called with info->tty==NULL\n");
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
return;
}
+
+ spin_lock_irqsave(&info->slock, flags);
tty = info->tty;
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
+
+ /* Loop sending data to FIFO until done or FIFO full */
while (1) {
if (tty->stopped || tty->hw_stopped)
break;
- c = MIN(info->xmit_fifo_room,
- MIN(info->xmit_cnt,
- XMIT_BUF_SIZE - info->xmit_tail));
+ c = MIN(info->xmit_fifo_room, MIN(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
if (c <= 0 || info->xmit_fifo_room <= 0)
break;
- sOutStrW(sGetTxRxDataIO(cp),
- info->xmit_buf + info->xmit_tail, c/2);
+ sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
if (c & 1)
- sOutB(sGetTxRxDataIO(cp),
- info->xmit_buf[info->xmit_tail + c -
- 1]);
+ sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
info->xmit_tail += c;
- info->xmit_tail &= XMIT_BUF_SIZE-1;
+ info->xmit_tail &= XMIT_BUF_SIZE - 1;
info->xmit_cnt -= c;
info->xmit_fifo_room -= c;
#ifdef ROCKET_DEBUG_INTR
- printk("tx %d chars...", c);
+ printk(KERN_INFO "tx %d chars...", c);
#endif
}
+
if (info->xmit_cnt == 0)
- xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
if (info->xmit_cnt < WAKEUP_CHARS) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
wake_up_interruptible(&tty->write_wait);
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+ wake_up_interruptible(&tty->poll_wait);
+#endif
}
+
+ spin_unlock_irqrestore(&info->slock, flags);
+
#ifdef ROCKET_DEBUG_INTR
- printk("(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
+ printk(KERN_INFO "(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
info->xmit_tail, info->xmit_fifo_room);
#endif
}
/*
- * This function is called for each port which has signalled an
- * interrupt. It checks what interrupts are pending and services
- * them.
+ * Called when a serial port signals it has read data in it's RX FIFO.
+ * It checks what interrupts are pending and services them, including
+ * receiving serial data.
*/
-static _INLINE_ void rp_handle_port(struct r_port *info)
+static void rp_handle_port(struct r_port *info)
{
CHANNEL_t *cp;
struct tty_struct *tty;
@@ -381,12 +515,13 @@
if (!info)
return;
- if ( (info->flags & ROCKET_INITIALIZED) == 0 ) {
- printk("rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n");
+
+ if ((info->flags & ROCKET_INITIALIZED) == 0) {
+ printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n");
return;
}
if (!info->tty) {
- printk("rp: WARNING: rp_handle_port called with info->tty==NULL\n");
+ printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->tty==NULL\n");
return;
}
cp = &info->channel;
@@ -394,25 +529,20 @@
IntMask = sGetChanIntID(cp) & info->intmask;
#ifdef ROCKET_DEBUG_INTR
- printk("rp_interrupt %02x...", IntMask);
+ printk(KERN_INFO "rp_interrupt %02x...", IntMask);
#endif
- ChanStatus= sGetChanStatus(cp);
+ ChanStatus = sGetChanStatus(cp);
if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */
rp_do_receive(info, tty, cp, ChanStatus);
}
-#if 0
- if (IntMask & SRC_INT) { /* Special receive condition */
- }
-#endif
if (IntMask & DELTA_CD) { /* CD change */
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || \
- defined(ROCKET_DEBUG_HANGUP))
- printk("ttyR%d CD now %s...", info->line,
+#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
+ printk(KERN_INFO "ttyR%d CD now %s...", info->line,
(ChanStatus & CD_ACT) ? "on" : "off");
#endif
if (!(ChanStatus & CD_ACT) && info->cd_status) {
#ifdef ROCKET_DEBUG_HANGUP
- printk("CD drop, calling hangup.\n");
+ printk(KERN_INFO "CD drop, calling hangup.\n");
#endif
tty_hangup(tty);
}
@@ -421,125 +551,166 @@
}
#ifdef ROCKET_DEBUG_INTR
if (IntMask & DELTA_CTS) { /* CTS change */
- printk("CTS change...\n");
+ printk(KERN_INFO "CTS change...\n");
}
if (IntMask & DELTA_DSR) { /* DSR change */
- printk("DSR change...\n");
+ printk(KERN_INFO "DSR change...\n");
}
#endif
}
/*
- * The top level polling routine.
+ * The top level polling routine. Repeats every 1/100 HZ (10ms).
*/
static void rp_do_poll(unsigned long dummy)
{
CONTROLLER_t *ctlp;
- int ctrl, aiop, ch, line;
+ int ctrl, aiop, ch, line, i;
unsigned int xmitmask;
- unsigned char CtlMask, AiopMask;
+ unsigned int CtlMask;
+ unsigned char AiopMask;
+ Word_t bit;
#ifdef TIME_STAT
- unsigned long loop_time;
- unsigned long long time_stat_tmp=0, time_stat_tmp2=0;
+ unsigned long low = 0, high = 0, loop_time;
+ unsigned long long time_stat_tmp = 0, time_stat_tmp2 = 0;
- rdtscll(time_stat_tmp);
-#endif /* TIME_STAT */
+ __asm__(".byte 0x0f,0x31":"=a"(low), "=d"(high));
+ time_stat_tmp = high;
+ time_stat_tmp <<= 32;
+ time_stat_tmp += low;
+#endif /* TIME_STAT */
- for (ctrl=0; ctrl < max_board; ctrl++) {
+ /* Walk through all the boards (ctrl's) */
+ for (ctrl = 0; ctrl < max_board; ctrl++) {
if (rcktpt_io_addr[ctrl] <= 0)
continue;
- ctlp= sCtlNumToCtlPtr(ctrl);
+ /* Get a ptr to the board's control struct */
+ ctlp = sCtlNumToCtlPtr(ctrl);
+
+ /* Get the interupt status from the board */
#ifdef CONFIG_PCI
- if(ctlp->BusType == isPCI)
- CtlMask= sPCIGetControllerIntStatus(ctlp);
+ if (ctlp->BusType == isPCI)
+ CtlMask = sPCIGetControllerIntStatus(ctlp);
else
#endif
- CtlMask= sGetControllerIntStatus(ctlp);
- for (aiop=0; CtlMask; CtlMask >>= 1, aiop++) {
- if (CtlMask & 1) {
- AiopMask= sGetAiopIntStatus(ctlp, aiop);
- for (ch=0; AiopMask; AiopMask >>= 1, ch++) {
+ CtlMask = sGetControllerIntStatus(ctlp);
+
+ /* Check if any AIOP read bits are set */
+ for (aiop = 0; CtlMask; aiop++) {
+ bit = ctlp->AiopIntrBits[aiop];
+ if (CtlMask & bit) {
+ CtlMask &= ~bit;
+ AiopMask = sGetAiopIntStatus(ctlp, aiop);
+
+ /* Check if any port read bits are set */
+ for (ch = 0; AiopMask; AiopMask >>= 1, ch++) {
if (AiopMask & 1) {
- line = (ctrl << 5) |
- (aiop << 3) | ch;
+
+ /* Get the line number (/dev/ttyRx number). */
+ /* Read the data from the port. */
+ line = GetLineNumber(ctrl, aiop, ch);
rp_handle_port(rp_table[line]);
}
}
}
}
+
xmitmask = xmit_flags[ctrl];
- for (line = ctrl << 5; xmitmask; xmitmask >>= 1, line++) {
- if (xmitmask & 1)
- rp_do_transmit(rp_table[line]);
+
+ /*
+ * xmit_flags contains bit-significant flags, indicating there is data
+ * to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port
+ * 1, ... (32 total possible). The variable i has the aiop and ch
+ * numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
+ */
+ if (xmitmask) {
+ for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
+ if (xmitmask & (1 << i)) {
+ aiop = (i & 0x18) >> 3;
+ ch = i & 0x07;
+ line = GetLineNumber(ctrl, aiop, ch);
+ rp_do_transmit(rp_table[line]);
+ }
+ }
}
}
/*
- * Reset the timer so we get called at the next clock tick.
+ * Reset the timer so we get called at the next clock tick (10ms).
*/
- if (rp_num_ports_open) {
- mod_timer(&rocket_timer, jiffies + 1);
- }
+ if (atomic_read(&rp_num_ports_open))
+ mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
+
#ifdef TIME_STAT
- rdtscll(time_stat_tmp2);
+ __asm__(".byte 0x0f,0x31":"=a"(low), "=d"(high));
+ time_stat_tmp2 = high;
+ time_stat_tmp2 <<= 32;
+ time_stat_tmp2 += low;
time_stat_tmp2 -= time_stat_tmp;
time_stat += time_stat_tmp2;
- if (time_counter == 0)
+ if (time_counter == 0)
time_stat_short = time_stat_long = time_stat_tmp2;
else {
- if ( time_stat_tmp2 < time_stat_short )
+ if (time_stat_tmp2 < time_stat_short)
time_stat_short = time_stat_tmp2;
- else if ( time_stat_tmp2 > time_stat_long )
+ else if (time_stat_tmp2 > time_stat_long)
time_stat_long = time_stat_tmp2;
}
- if ( ++time_counter == TIME_COUNTER ) {
- loop_time = (unsigned long) ( ((unsigned long)(time_stat >> 32) * ( (unsigned long)(0xffffffff)/(TIME_STAT_CPU * TIME_COUNTER) ) ) + ((unsigned long)time_stat/(TIME_STAT_CPU*TIME_COUNTER)));
+ if (++time_counter == TIME_COUNTER) {
+ loop_time =
+ (unsigned
+ long) (((unsigned long) (time_stat >> 32) *
+ ((unsigned long) (0xffffffff) /
+ (TIME_STAT_CPU * TIME_COUNTER))) +
+ ((unsigned long) time_stat /
+ (TIME_STAT_CPU * TIME_COUNTER)));
#ifdef TIME_STAT_VERBOSE
- printk("rp_do_poll: Interrupt Timings\n");
- printk(" %5ld iterations; %ld us min,\n",
- (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU));
- printk(" %5ld us max, %ld us average per iteration.\n",
- (time_stat_long/TIME_STAT_CPU), loop_time);
- printk("We want to use < 5,000 us for an iteration.\n");
-#else /* TIME_STAT_VERBOSE */
- printk("rp: %ld loops: %ld min, %ld max, %ld us/loop.\n",
- (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU),
- (time_stat_long/TIME_STAT_CPU), loop_time);
-#endif /* TIME_STAT_VERBOSE */
+ printk(KERN_INFO "rp_do_poll: Interrupt Timings\n");
+ printk(KERN_INFO " %5ld iterations; %ld us min,\n",
+ (long) TIME_COUNTER,
+ (time_stat_short / TIME_STAT_CPU));
+ printk(KERN_INFO " %5ld us max, %ld us average per iteration.\n",
+ (time_stat_long / TIME_STAT_CPU), loop_time);
+ printk(KERN_INFO "We want to use < 5,000 us for an iteration.\n");
+#else /* TIME_STAT_VERBOSE */
+ printk(KERN_INFO "rp: %ld loops: %ld min, %ld max, %ld us/loop.\n",
+ (long) TIME_COUNTER,
+ (time_stat_short / TIME_STAT_CPU),
+ (time_stat_long / TIME_STAT_CPU), loop_time);
+#endif /* TIME_STAT_VERBOSE */
time_counter = time_stat = 0;
time_stat_short = time_stat_long = 0;
}
-#endif /* TIME_STAT */
+#endif /* TIME_STAT */
}
-/*
- * Here ends the interrupt/polling routine.
- */
-
/*
- * This function initializes the r_port structure, as well as enabling
- * the port on the RocketPort board.
+ * Initializes the r_port structure for a port, as well as enabling the port on
+ * the board.
+ * Inputs: board, aiop, chan numbers
*/
-static void init_r_port(int board, int aiop, int chan)
+static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
{
+ unsigned rocketMode;
struct r_port *info;
int line;
CONTROLLER_T *ctlp;
- CHANNEL_t *cp;
-
- line = (board << 5) | (aiop << 3) | chan;
- ctlp= sCtlNumToCtlPtr(board);
+ /* Get the next available line number */
+ line = SetLineNumber(board, aiop, chan);
- info = kmalloc(sizeof(struct r_port), GFP_KERNEL);
+ ctlp = sCtlNumToCtlPtr(board);
+
+ /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
+ info = kmalloc(sizeof (struct r_port), GFP_KERNEL);
if (!info) {
- printk("Couldn't allocate info struct for line #%d\n", line);
+ printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line);
return;
}
- memset(info, 0, sizeof(struct r_port));
-
+ memset(info, 0, sizeof (struct r_port));
+
info->magic = RPORT_MAGIC;
info->line = line;
info->ctlp = ctlp;
@@ -551,31 +722,73 @@
info->normal_termios = rocket_driver.init_termios;
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
+ info->flags &= ~ROCKET_MODE_MASK;
+ switch (pc104[board][line]) {
+ case 422:
+ info->flags |= ROCKET_MODE_RS422;
+ break;
+ case 485:
+ info->flags |= ROCKET_MODE_RS485;
+ break;
+ case 232:
+ default:
+ info->flags |= ROCKET_MODE_RS232;
+ break;
+ }
- info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD |
- DELTA_CTS | DELTA_DSR;
+ info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
- printk("Rocketport sInitChan(%d, %d, %d) failed!\n",
- board, aiop, chan);
+ printk(KERN_INFO "RocketPort sInitChan(%d, %d, %d) failed!\n", board, aiop, chan);
kfree(info);
return;
}
- cp = &info->channel;
+
+ rocketMode = info->flags & ROCKET_MODE_MASK;
+
+ if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
+ sEnRTSToggle(&info->channel);
+ else
+ sDisRTSToggle(&info->channel);
+
+ if (ctlp->boardType == ROCKET_TYPE_PC104) {
+ switch (rocketMode) {
+ case ROCKET_MODE_RS485:
+ sSetInterfaceMode(&info->channel, InterfaceModeRS485);
+ break;
+ case ROCKET_MODE_RS422:
+ sSetInterfaceMode(&info->channel, InterfaceModeRS422);
+ break;
+ case ROCKET_MODE_RS232:
+ default:
+ if (info->flags & ROCKET_RTS_TOGGLE)
+ sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
+ else
+ sSetInterfaceMode(&info->channel, InterfaceModeRS232);
+ break;
+ }
+ }
+ spin_lock_init(&info->slock);
+ sema_init(&info->write_sem, 1);
rp_table[line] = info;
+#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
+ if (pci_dev)
+ tty_register_device(&rocket_driver, line, &pci_dev->dev);
+#endif
}
-
/*
- * This routine configures a rocketport port so according to its
- * termio settings.
+ * Configures a rocketport port according to its termio settings. Called from
+ * user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
*/
-static void configure_r_port(struct r_port *info)
+static void configure_r_port(struct r_port *info,
+ struct termios *old_termios)
{
unsigned cflag;
- unsigned long flags;
- int bits, baud;
- CHANNEL_t *cp;
-
+ unsigned long flags;
+ unsigned rocketMode;
+ int bits, baud, divisor;
+ CHANNEL_t *cp;
+
if (!info->tty || !info->tty->termios)
return;
cp = &info->channel;
@@ -589,13 +802,13 @@
sSetData7(cp);
bits = 9;
}
- if (cflag & CSTOPB) {
+ if (cflag & CSTOPB) {
sSetStop2(cp);
bits++;
} else {
sSetStop1(cp);
}
-
+
if (cflag & PARENB) {
sEnParity(cp);
bits++;
@@ -607,14 +820,28 @@
} else {
sDisParity(cp);
}
-
+
/* baud rate */
baud = tty_get_baud_rate(info->tty);
if (!baud)
baud = 9600;
+ divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
+ if ((divisor >= 8192 || divisor < 0) && old_termios) {
+ info->tty->termios->c_cflag &= ~CBAUD;
+ info->tty->termios->c_cflag |=
+ (old_termios->c_cflag & CBAUD);
+ baud = tty_get_baud_rate(info->tty);
+ if (!baud)
+ baud = 9600;
+ divisor = (rp_baud_base[info->board] / baud) - 1;
+ }
+ if (divisor >= 8192 || divisor < 0) {
+ baud = 9600;
+ divisor = (rp_baud_base[info->board] / baud) - 1;
+ }
info->cps = baud / bits;
- sSetBaud(cp, (rp_baud_base/baud) - 1);
-
+ sSetBaud(cp, divisor);
+
if (cflag & CRTSCTS) {
info->intmask |= DELTA_CTS;
sEnCTSFlowCtl(cp);
@@ -622,17 +849,16 @@
info->intmask &= ~DELTA_CTS;
sDisCTSFlowCtl(cp);
}
- sSetRTS(&info->channel);
- if (cflag & CLOCAL)
+ if (cflag & CLOCAL) {
info->intmask &= ~DELTA_CD;
- else {
- save_flags(flags); cli();
+ } else {
+ spin_lock_irqsave(&info->slock, flags);
if (sGetChanStatus(cp) & CD_ACT)
info->cd_status = 1;
else
info->cd_status = 0;
info->intmask |= DELTA_CD;
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->slock, flags);
}
/*
@@ -654,7 +880,7 @@
sClrTxXOFF(cp);
}
#endif
-
+
/*
* Set up ignore/read mask words
*/
@@ -679,263 +905,281 @@
if (I_IGNPAR(info->tty))
info->ignore_status_mask |= STMRCVROVRH;
}
+
+ rocketMode = info->flags & ROCKET_MODE_MASK;
+
+ if ((info->flags & ROCKET_RTS_TOGGLE)
+ || (rocketMode == ROCKET_MODE_RS485))
+ sEnRTSToggle(cp);
+ else
+ sDisRTSToggle(cp);
+
+ sSetRTS(&info->channel);
+
+ if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
+ switch (rocketMode) {
+ case ROCKET_MODE_RS485:
+ sSetInterfaceMode(cp, InterfaceModeRS485);
+ break;
+ case ROCKET_MODE_RS422:
+ sSetInterfaceMode(cp, InterfaceModeRS422);
+ break;
+ case ROCKET_MODE_RS232:
+ default:
+ if (info->flags & ROCKET_RTS_TOGGLE)
+ sSetInterfaceMode(cp, InterfaceModeRS232T);
+ else
+ sSetInterfaceMode(cp, InterfaceModeRS232);
+ break;
+ }
+ }
}
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
+/* info->count is considered critical, protected by spinlocks. */
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
struct r_port *info)
{
DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0, extra_count = 0;
- unsigned long flags;
+ int retval;
+ int do_clocal = 0, extra_count = 0;
+ unsigned long flags;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp))
- return ((info->flags & ROCKET_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
+ return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
if (info->flags & ROCKET_CLOSING) {
interruptible_sleep_on(&info->close_wait);
- return ((info->flags & ROCKET_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
+ return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
/*
* If non-blocking mode is set, or the port is not enabled,
* then make the check up front and then exit.
*/
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
+ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
info->flags |= ROCKET_NORMAL_ACTIVE;
return 0;
}
-
if (tty->termios->c_cflag & CLOCAL)
do_clocal = 1;
/*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * rp_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
+ * Block waiting for the carrier detect and the line to become free. While we are in
+ * this loop, info->count is dropped by one, so that rp_close() knows when to free things.
+ * We restore it upon exit, either normal or abnormal.
*/
retval = 0;
add_wait_queue(&info->open_wait, &wait);
#ifdef ROCKET_DEBUG_OPEN
- printk("block_til_ready before block: ttyR%d, count = %d\n",
- info->line, info->count);
+ printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->count);
#endif
- save_flags(flags); cli();
+ spin_lock_irqsave(&info->slock, flags);
+
+#ifdef ROCKET_DISABLE_SIMUSAGE
+ info->flags |= ROCKET_NORMAL_ACTIVE;
+#else
if (!tty_hung_up_p(filp)) {
extra_count = 1;
info->count--;
}
- restore_flags(flags);
+#endif
info->blocked_open++;
+
+ spin_unlock_irqrestore(&info->slock, flags);
+
while (1) {
- if ((tty->termios->c_cflag & CBAUD)) {
+ if (tty->termios->c_cflag & CBAUD) {
sSetDTR(&info->channel);
sSetRTS(&info->channel);
}
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(info->flags & ROCKET_INITIALIZED)) {
+ if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) {
if (info->flags & ROCKET_HUP_NOTIFY)
retval = -EAGAIN;
else
- retval = -ERESTARTSYS;
+ retval = -ERESTARTSYS;
break;
}
- if (!(info->flags & ROCKET_CLOSING) &&
- (do_clocal || (sGetChanStatusLo(&info->channel) &
- CD_ACT)))
+ if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
#ifdef ROCKET_DEBUG_OPEN
- printk("block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
- info->line, info->count, info->flags);
+ printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
+ info->line, info->count, info->flags);
#endif
- schedule();
+ schedule(); /* Don't hold spinlock here, will hang PC */
}
current->state = TASK_RUNNING;
remove_wait_queue(&info->open_wait, &wait);
- cli();
+
+ spin_lock_irqsave(&info->slock, flags);
+
if (extra_count)
info->count++;
- restore_flags(flags);
info->blocked_open--;
+
+ spin_unlock_irqrestore(&info->slock, flags);
+
#ifdef ROCKET_DEBUG_OPEN
- printk("block_til_ready after blocking: ttyR%d, count = %d\n",
+ printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
info->line, info->count);
#endif
if (retval)
return retval;
info->flags |= ROCKET_NORMAL_ACTIVE;
return 0;
-}
+}
/*
- * This routine is called whenever a rocketport board is opened.
+ * Exception handler that opens a serial port. Creates xmit_buf storage, fills in
+ * port's r_port struct. Initializes the port hardware.
*/
-static int rp_open(struct tty_struct *tty, struct file * filp)
+static int rp_open(struct tty_struct *tty, struct file *filp)
{
struct r_port *info;
- int line, retval;
- CHANNEL_t *cp;
+ int line = 0, retval;
+ CHANNEL_t *cp;
unsigned long page;
-
- line = tty->index;
- if ((line < 0) || (line >= MAX_RP_PORTS))
- return -ENODEV;
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
- page = get_zeroed_page(GFP_KERNEL);
+
+#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
+ line = TTY_GET_LINE(tty);
+#else
+ line = MINOR(tty->device) - TTY_DRIVER_MINOR_START(tty);
+#endif
+
+ if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL))
+ return -ENXIO;
+
+ page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
- tty->driver_data = info = rp_table[line];
-
if (info->flags & ROCKET_CLOSING) {
interruptible_sleep_on(&info->close_wait);
free_page(page);
- return ((info->flags & ROCKET_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
+ return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
-
+
/*
- * We must not sleep from here until the port is marked fully
- * in use.
+ * We must not sleep from here until the port is marked fully in use.
*/
- if (rp_table[line] == NULL) {
- tty->flags = (1 << TTY_IO_ERROR);
- free_page(page);
- return 0;
- }
- if (!info) {
- printk("rp_open: rp_table[%d] is NULL!\n", line);
- free_page(page);
- return -EIO;
- }
if (info->xmit_buf)
free_page(page);
else
info->xmit_buf = (unsigned char *) page;
- info->tty = tty;
- if (info->flags & ROCKET_CLOSING) {
- interruptible_sleep_on(&info->close_wait);
- return ((info->flags & ROCKET_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
- }
+ tty->driver_data = info;
+ info->tty = tty;
if (info->count++ == 0) {
- rp_num_ports_open++;
+#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
+ MOD_INC_USE_COUNT;
+#endif
+ atomic_inc(&rp_num_ports_open);
+
#ifdef ROCKET_DEBUG_OPEN
- printk("rocket mod++ = %d...", rp_num_ports_open);
+ printk(KERN_INFO "rocket mod++ = %d...", atomic_read(&rp_num_ports_open));
#endif
}
#ifdef ROCKET_DEBUG_OPEN
- printk("rp_open ttyR%d, count=%d\n", info->line, info->count);
+ printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->count);
#endif
+
/*
* Info->count is now 1; so it's safe to sleep now.
*/
-
- cp = &info->channel;
- sSetRxTrigger(cp, TRIG_1);
- if (sGetChanStatus(cp) & CD_ACT)
- info->cd_status = 1;
- else
- info->cd_status = 0;
- sDisRxStatusMode(cp);
- sFlushRxFIFO(cp);
- sFlushTxFIFO(cp);
-
- sEnInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
- sSetRxTrigger(cp, TRIG_1);
+ info->session = current->session;
+ info->pgrp = current->pgrp;
- sGetChanStatus(cp);
- sDisRxStatusMode(cp);
- sClrTxXOFF(cp);
-
- sDisCTSFlowCtl(cp);
- sDisTxSoftFlowCtl(cp);
-
- sEnRxFIFO(cp);
- sEnTransmit(cp);
+ if ((info->flags & ROCKET_INITIALIZED) == 0) {
+ cp = &info->channel;
+ sSetRxTrigger(cp, TRIG_1);
+ if (sGetChanStatus(cp) & CD_ACT)
+ info->cd_status = 1;
+ else
+ info->cd_status = 0;
+ sDisRxStatusMode(cp);
+ sFlushRxFIFO(cp);
+ sFlushTxFIFO(cp);
- info->flags |= ROCKET_INITIALIZED;
+ sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
+ sSetRxTrigger(cp, TRIG_1);
- /*
- * Set up the tty->alt_speed kludge
- */
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- info->tty->alt_speed = 460800;
+ sGetChanStatus(cp);
+ sDisRxStatusMode(cp);
+ sClrTxXOFF(cp);
- configure_r_port(info);
- if (tty->termios->c_cflag & CBAUD) {
- sSetDTR(cp);
- sSetRTS(cp);
+ sDisCTSFlowCtl(cp);
+ sDisTxSoftFlowCtl(cp);
+
+ sEnRxFIFO(cp);
+ sEnTransmit(cp);
+
+ info->flags |= ROCKET_INITIALIZED;
+
+ /*
+ * Set up the tty->alt_speed kludge
+ */
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
+ info->tty->alt_speed = 57600;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
+ info->tty->alt_speed = 115200;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
+ info->tty->alt_speed = 230400;
+ if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
+ info->tty->alt_speed = 460800;
+
+ configure_r_port(info, NULL);
+ if (tty->termios->c_cflag & CBAUD) {
+ sSetDTR(cp);
+ sSetRTS(cp);
+ }
}
-
- mod_timer(&rocket_timer, jiffies + 1);
+ /* Starts (or resets) the maint polling loop */
+ mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
retval = block_til_ready(tty, filp, info);
if (retval) {
#ifdef ROCKET_DEBUG_OPEN
- printk("rp_open returning after block_til_ready with %d\n",
- retval);
+ printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
#endif
return retval;
}
if ((info->count == 1) && (info->flags & ROCKET_SPLIT_TERMIOS)) {
*tty->termios = info->normal_termios;
- configure_r_port(info);
+ configure_r_port(info, NULL);
}
-
return 0;
}
-static void rp_close(struct tty_struct *tty, struct file * filp)
+/*
+ * Exception handler that closes a serial port. info->count is considered critical.
+ */
+static void rp_close(struct tty_struct *tty, struct file *filp)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
unsigned long flags;
int timeout;
- CHANNEL_t *cp;
+ CHANNEL_t *cp;
- if (rocket_paranoia_check(info, tty->name, "rp_close"))
+ if (rocket_paranoia_check(info, "rp_close"))
return;
#ifdef ROCKET_DEBUG_OPEN
- printk("rp_close ttyR%d, count = %d\n", info->line, info->count);
+ printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->count);
#endif
-
- save_flags(flags); cli();
-
- if (tty_hung_up_p(filp)) {
- restore_flags(flags);
+
+ if (tty_hung_up_p(filp))
return;
- }
+ spin_lock_irqsave(&info->slock, flags);
+
if ((tty->count == 1) && (info->count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
@@ -944,27 +1188,23 @@
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
- printk("rp_close: bad serial port count; tty->count is 1, "
+ printk(KERN_INFO "rp_close: bad serial port count; tty->count is 1, "
"info->count is %d\n", info->count);
info->count = 1;
}
if (--info->count < 0) {
- printk("rp_close: bad serial port count for ttyR%d: %d\n",
+ printk(KERN_INFO "rp_close: bad serial port count for ttyR%d: %d\n",
info->line, info->count);
info->count = 0;
}
if (info->count) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->slock, flags);
return;
}
info->flags |= ROCKET_CLOSING;
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (info->flags & ROCKET_NORMAL_ACTIVE)
- info->normal_termios = *tty->termios;
-
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ info->normal_termios = *tty->termios;
cp = &info->channel;
/*
@@ -989,29 +1229,30 @@
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
- timeout = (sGetTxCnt(cp)+1) * HZ / info->cps;
+ timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
if (timeout == 0)
timeout = 1;
rp_wait_until_sent(tty, timeout);
-
- xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
sDisTransmit(cp);
- sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
+ sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
sDisCTSFlowCtl(cp);
sDisTxSoftFlowCtl(cp);
sClrTxXOFF(cp);
- sFlushRxFIFO(cp);
+ sFlushRxFIFO(cp);
sFlushTxFIFO(cp);
sClrRTS(cp);
- if (C_HUPCL(tty)) {
+ if (C_HUPCL(tty))
sClrDTR(cp);
- }
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
+
+ if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
+ TTY_DRIVER_FLUSH_BUFFER(tty);
if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);
- xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
if (info->blocked_open) {
if (info->close_delay) {
current->state = TASK_INTERRUPTIBLE;
@@ -1027,27 +1268,27 @@
info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
tty->closing = 0;
wake_up_interruptible(&info->close_wait);
-
- rp_num_ports_open--;
-#ifdef ROCKET_DEBUG_OPEN
- printk("rocket mod-- = %d...", rp_num_ports_open);
+
+#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
+ MOD_DEC_USE_COUNT;
#endif
- restore_flags(flags);
-
+ atomic_dec(&rp_num_ports_open);
+
#ifdef ROCKET_DEBUG_OPEN
- printk("rp_close ttyR%d complete shutdown\n", info->line);
+ printk(KERN_INFO "rocket mod-- = %d...", atomic_read(&rp_num_ports_open));
+ printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
#endif
-
+
}
-static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios)
+static void rp_set_termios(struct tty_struct *tty,
+ struct termios *old_termios)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
unsigned cflag;
-
- if (rocket_paranoia_check(info, tty->name, "rp_set_termios"))
+ if (rocket_paranoia_check(info, "rp_set_termios"))
return;
cflag = tty->termios->c_cflag;
@@ -1058,88 +1299,103 @@
/*
* This driver doesn't support CS5 or CS6
*/
- if (((cflag & CSIZE) == CS5) ||
- ((cflag & CSIZE) == CS6))
- tty->termios->c_cflag = ((cflag & ~CSIZE) |
- (old_termios->c_cflag & CSIZE));
+ if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
+ tty->termios->c_cflag =
+ ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
- configure_r_port(info);
+ configure_r_port(info, old_termios);
cp = &info->channel;
/* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(tty->termios->c_cflag & CBAUD)) {
+ if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
sClrDTR(cp);
sClrRTS(cp);
}
-
+
/* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (tty->termios->c_cflag & CBAUD)) {
- if (!tty->hw_stopped ||
- !(tty->termios->c_cflag & CRTSCTS)) {
+ if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
+ if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
sSetRTS(cp);
- }
sSetDTR(cp);
}
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+
+ if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
rp_start(tty);
}
}
-/*
- * Here are the routines used by rp_ioctl
- */
static void rp_break(struct tty_struct *tty, int break_state)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
unsigned long flags;
-
- if (rocket_paranoia_check(info, tty->name, "rp_break"))
+
+ if (rocket_paranoia_check(info, "rp_break"))
return;
- save_flags(flags); cli();
- if (break_state == -1) {
+ spin_lock_irqsave(&info->slock, flags);
+ if (break_state == -1)
sSendBreak(&info->channel);
- } else {
+ else
sClrBreak(&info->channel);
- }
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->slock, flags);
+}
+
+/*
+ * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
+ * the UPCI boards was added, it was decided to make this a function because
+ * the macro was getting too complicated. All cases except the first one
+ * (UPCIRingInd) are taken directly from the original macro.
+ */
+static int sGetChanRI(CHANNEL_T * ChP)
+{
+ CONTROLLER_t *CtlP = ChP->CtlP;
+ int ChanNum = ChP->ChanNum;
+ int RingInd = 0;
+
+ if (CtlP->UPCIRingInd)
+ RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
+ else if (CtlP->AltChanRingIndicator)
+ RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
+ else if (CtlP->boardType == ROCKET_TYPE_PC104)
+ RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
+
+ return RingInd;
}
-static int get_modem_info(struct r_port * info, unsigned int *value)
+/********************************************************************************************/
+/* Here are the routines used by rp_ioctl. These are all called from exception handlers. */
+
+static int get_modem_info(struct r_port *info, unsigned int *value)
{
unsigned int control, result, ChanStatus;
ChanStatus = sGetChanStatusLo(&info->channel);
-
+
control = info->channel.TxControl[3];
- result = ((control & SET_RTS) ? TIOCM_RTS : 0)
- | ((control & SET_DTR) ? TIOCM_DTR : 0)
- | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0)
- /* TIOCM_RNG not supported */
- | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0)
- | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
+ result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
+ ((control & SET_DTR) ? TIOCM_DTR : 0) |
+ ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
+ (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
+ ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
+ ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
- if (copy_to_user(value, &result, sizeof(int)))
+ if (copy_to_user(value, &result, sizeof (int)))
return -EFAULT;
return 0;
}
-static int set_modem_info(struct r_port * info, unsigned int cmd,
+static int set_modem_info(struct r_port *info, unsigned int cmd,
unsigned int *value)
{
unsigned int arg;
- if (copy_from_user(&arg, value, sizeof(int)))
+ if (copy_from_user(&arg, value, sizeof (int)))
return -EFAULT;
switch (cmd) {
- case TIOCMBIS:
+ case TIOCMBIS:
if (arg & TIOCM_RTS)
info->channel.TxControl[3] |= SET_RTS;
if (arg & TIOCM_DTR)
@@ -1152,59 +1408,103 @@
info->channel.TxControl[3] &= ~SET_DTR;
break;
case TIOCMSET:
- info->channel.TxControl[3] =
- ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR))
- | ((arg & TIOCM_RTS) ? SET_RTS : 0)
- | ((arg & TIOCM_DTR) ? SET_DTR : 0));
+ info->channel.TxControl[3] = ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR)) |
+ ((arg & TIOCM_RTS) ? SET_RTS : 0) |
+ ((arg & TIOCM_DTR) ? SET_DTR : 0));
break;
default:
return -EINVAL;
}
- sOutDW(info->channel.IndexAddr,
- *(DWord_t *) &(info->channel.TxControl[0]));
-
+ sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
+ return 0;
+}
+
+#if LINUX_VERSION_CODE > VERSION_CODE(2,5,0)
+
+/*
+ * Returns the state of the serial modem control lines. These next 2 functions
+ * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
+ */
+static int rp_tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct r_port *info = (struct r_port *)tty->driver_data;
+ unsigned int control, result, ChanStatus;
+
+ ChanStatus = sGetChanStatusLo(&info->channel);
+ control = info->channel.TxControl[3];
+ result = ((control & SET_RTS) ? TIOCM_RTS : 0) |
+ ((control & SET_DTR) ? TIOCM_DTR : 0) |
+ ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
+ (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
+ ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
+ ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
+
+ return result;
+}
+
+/*
+ * Sets the modem control lines
+ */
+static int rp_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct r_port *info = (struct r_port *)tty->driver_data;
+
+ if (set & TIOCM_RTS)
+ info->channel.TxControl[3] |= SET_RTS;
+ if (set & TIOCM_DTR)
+ info->channel.TxControl[3] |= SET_DTR;
+ if (clear & TIOCM_RTS)
+ info->channel.TxControl[3] &= ~SET_RTS;
+ if (clear & TIOCM_DTR)
+ info->channel.TxControl[3] &= ~SET_DTR;
+
+ sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
return 0;
}
-static int get_config(struct r_port * info, struct rocket_config * retinfo)
+#endif /* Linux > 2.5 */
+
+static int get_config(struct r_port *info, struct rocket_config *retinfo)
{
struct rocket_config tmp;
-
+
if (!retinfo)
return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
+ memset(&tmp, 0, sizeof (tmp));
tmp.line = info->line;
tmp.flags = info->flags;
tmp.close_delay = info->close_delay;
tmp.closing_wait = info->closing_wait;
tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
-
- if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+
+ if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
return -EFAULT;
return 0;
}
-static int set_config(struct r_port * info, struct rocket_config * new_info)
+static int set_config(struct r_port *info, struct rocket_config *new_info)
{
struct rocket_config new_serial;
- if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+ if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
return -EFAULT;
+#ifdef CAP_SYS_ADMIN
if (!capable(CAP_SYS_ADMIN))
+#else
+ if (!suser())
+#endif
{
- if ((new_serial.flags & ~ROCKET_USR_MASK) !=
- (info->flags & ~ROCKET_USR_MASK))
+ if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
return -EPERM;
- info->flags = ((info->flags & ~ROCKET_USR_MASK) |
- (new_serial.flags & ROCKET_USR_MASK));
- configure_r_port(info);
+ info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
+ configure_r_port(info, 0);
return 0;
}
-
- info->flags = ((info->flags & ~ROCKET_FLAGS) |
- (new_serial.flags & ROCKET_FLAGS));
+
+ info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
info->close_delay = new_serial.close_delay;
info->closing_wait = new_serial.closing_wait;
@@ -1216,117 +1516,162 @@
info->tty->alt_speed = 230400;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
info->tty->alt_speed = 460800;
-
- configure_r_port(info);
+
+ configure_r_port(info, 0);
return 0;
}
-static int get_ports(struct r_port * info, struct rocket_ports * retports)
+/*
+ * This function fills in a rocket_ports struct with information
+ * about what boards/ports are in the system. This info is passed
+ * to user space. See setrocket.c where the info is used to create
+ * the /dev/ttyRx ports.
+ */
+static int get_ports(struct r_port *info, struct rocket_ports *retports)
{
struct rocket_ports tmp;
- int board, port, index;
-
+ int board;
+
if (!retports)
return -EFAULT;
- memset(&tmp, 0, sizeof(tmp));
+ memset(&tmp, 0, sizeof (tmp));
tmp.tty_major = rocket_driver.major;
- tmp.callout_major = 0;
+
for (board = 0; board < 4; board++) {
- index = board << 5;
- for (port = 0; port < 32; port++, index++) {
- if (rp_table[index])
- tmp.port_bitmap[board] |= 1 << port;
- }
+ tmp.rocketModel[board].model = rocketModel[board].model;
+ strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
+ tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
+ tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
+ tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
}
- if (copy_to_user(retports,&tmp,sizeof(*retports)))
+ if (copy_to_user(retports, &tmp, sizeof (*retports)))
return -EFAULT;
return 0;
}
-static int rp_ioctl(struct tty_struct *tty, struct file * file,
+static int reset_rm2(struct r_port *info, unsigned long arg)
+{
+ int reset;
+
+ if (copy_from_user(&reset, (void *) arg, sizeof (int)))
+ return -EFAULT;
+ if (reset)
+ reset = 1;
+
+ if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
+ rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
+ return -EINVAL;
+
+ if (info->ctlp->BusType == isISA)
+ sModemReset(info->ctlp, info->chan, reset);
+ else
+ sPCIModemReset(info->ctlp, info->chan, reset);
+
+ return 0;
+}
+
+static int get_version(struct r_port *info, struct rocket_version *retvers)
+{
+ if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
+ return -EFAULT;
+ return 0;
+}
+
+/* IOCTL call handler into the driver */
+static int rp_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
- if (cmd != RCKP_GET_PORTS &&
- rocket_paranoia_check(info, tty->name, "rp_ioctl"))
- return -ENODEV;
+ if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
+ return -ENXIO;
switch (cmd) {
-
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
- case RCKP_GET_STRUCT:
- if (copy_to_user((void *) arg, info,
- sizeof(struct r_port)))
- return -EFAULT;
- return 0;
-
- case RCKP_GET_CONFIG:
- return get_config(info, (struct rocket_config *) arg);
- case RCKP_SET_CONFIG:
- return set_config(info, (struct rocket_config *) arg);
-
- case RCKP_GET_PORTS:
- return get_ports(info, (struct rocket_ports *) arg);
- default:
- return -ENOIOCTLCMD;
- }
+ case TIOCMGET:
+ return get_modem_info(info, (unsigned int *) arg);
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return set_modem_info(info, cmd, (unsigned int *) arg);
+ case RCKP_GET_STRUCT:
+ if (copy_to_user((void *) arg, info, sizeof (struct r_port)))
+ return -EFAULT;
+ return 0;
+ case RCKP_GET_CONFIG:
+ return get_config(info, (struct rocket_config *) arg);
+ case RCKP_SET_CONFIG:
+ return set_config(info, (struct rocket_config *) arg);
+ case RCKP_GET_PORTS:
+ return get_ports(info, (struct rocket_ports *) arg);
+ case RCKP_RESET_RM2:
+ return reset_rm2(info, arg);
+ case RCKP_GET_VERSION:
+ return get_version(info, (struct rocket_version *) arg);
+ default:
+ return -ENOIOCTLCMD;
+ }
return 0;
}
+#if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE))
+static char *rp_tty_name(struct tty_struct *tty, char *buf)
+{
+ if (tty)
+ sprintf(buf, "%s%d", TTY_DRIVER_NAME(tty), MINOR(tty->device) - TTY_DRIVER_MINOR_START(tty) + TTY_DRIVER_NAME_BASE);
+ else
+ strcpy(buf, "NULL tty");
+ return buf;
+}
+#endif
+
static void rp_send_xchar(struct tty_struct *tty, char ch)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
- if (rocket_paranoia_check(info, tty->name, "rp_send_xchar"))
+ if (rocket_paranoia_check(info, "rp_send_xchar"))
return;
cp = &info->channel;
- if (sGetTxCnt(cp))
+ if (sGetTxCnt(cp))
sWriteTxPrioByte(cp, ch);
else
sWriteTxByte(sGetTxRxDataIO(cp), ch);
}
-static void rp_throttle(struct tty_struct * tty)
+static void rp_throttle(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", tty->name,
+ char buf[64];
+
+ printk(KERN_INFO "throttle %s: %d....\n", rp_tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
- if (rocket_paranoia_check(info, tty->name, "rp_throttle"))
+ if (rocket_paranoia_check(info, "rp_throttle"))
return;
cp = &info->channel;
if (I_IXOFF(tty))
rp_send_xchar(tty, STOP_CHAR(tty));
-
+
sClrRTS(&info->channel);
}
-static void rp_unthrottle(struct tty_struct * tty)
+static void rp_unthrottle(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", tty->name,
+ char buf[64];
+
+ printk(KERN_INFO "unthrottle %s: %d....\n", rp_tty_name(tty, buf),
tty->ldisc.chars_in_buffer(tty));
#endif
- if (rocket_paranoia_check(info, tty->name, "rp_throttle"))
+ if (rocket_paranoia_check(info, "rp_throttle"))
return;
cp = &info->channel;
@@ -1346,15 +1691,15 @@
*/
static void rp_stop(struct tty_struct *tty)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
#ifdef ROCKET_DEBUG_FLOW
- char buf[64];
-
- printk("stop %s: %d %d....\n", tty->name,
+ char buf[64];
+
+ printk(KERN_INFO "stop %s: %d %d....\n", rp_tty_name(tty, buf),
info->xmit_cnt, info->xmit_fifo_room);
#endif
- if (rocket_paranoia_check(info, tty->name, "rp_stop"))
+ if (rocket_paranoia_check(info, "rp_stop"))
return;
if (sGetTxCnt(&info->channel))
@@ -1363,19 +1708,20 @@
static void rp_start(struct tty_struct *tty)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
#ifdef ROCKET_DEBUG_FLOW
- char buf[64];
-
- printk("start %s: %d %d....\n", tty->name,
+ char buf[64];
+
+ printk(KERN_INFO "start %s: %d %d....\n", rp_tty_name(tty, buf),
info->xmit_cnt, info->xmit_fifo_room);
#endif
- if (rocket_paranoia_check(info, tty->name, "rp_stop"))
+ if (rocket_paranoia_check(info, "rp_stop"))
return;
sEnTransmit(&info->channel);
- xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
+ set_bit((info->aiop * 8) + info->chan,
+ (void *) &xmit_flags[info->board]);
}
/*
@@ -1383,21 +1729,22 @@
*/
static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = (struct r_port *) tty->driver_data;
CHANNEL_t *cp;
unsigned long orig_jiffies;
int check_time, exit_time;
int txcnt;
-
- if (rocket_paranoia_check(info, tty->name, "rp_wait_until_sent"))
+
+ if (rocket_paranoia_check(info, "rp_wait_until_sent"))
return;
cp = &info->channel;
orig_jiffies = jiffies;
#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk("In RP_wait_until_sent(%d) (jiff=%lu)...", timeout, jiffies);
- printk("cps=%d...", info->cps);
+ printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...", timeout,
+ jiffies);
+ printk(KERN_INFO "cps=%d...", info->cps);
#endif
while (1) {
txcnt = sGetTxCnt(cp);
@@ -1405,8 +1752,9 @@
if (sGetChanStatusLo(cp) & TXSHRMT)
break;
check_time = (HZ / info->cps) / 5;
- } else
+ } else {
check_time = HZ * txcnt / info->cps;
+ }
if (timeout) {
exit_time = orig_jiffies + timeout - jiffies;
if (exit_time <= 0)
@@ -1417,8 +1765,7 @@
if (check_time == 0)
check_time = 1;
#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk("txcnt = %d (jiff=%lu,check=%d)...", txcnt,
- jiffies, check_time);
+ printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...", txcnt, jiffies, check_time);
#endif
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(check_time);
@@ -1427,7 +1774,7 @@
}
current->state = TASK_RUNNING;
#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
- printk("txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
+ printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
#endif
}
@@ -1436,32 +1783,26 @@
*/
static void rp_hangup(struct tty_struct *tty)
{
- CHANNEL_t *cp;
- struct r_port * info = (struct r_port *)tty->driver_data;
-
- if (rocket_paranoia_check(info, tty->name, "rp_hangup"))
+ CHANNEL_t *cp;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+
+ if (rocket_paranoia_check(info, "rp_hangup"))
return;
#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
- printk("rp_hangup of ttyR%d...", info->line);
+ printk(KERN_INFO "rp_hangup of ttyR%d...", info->line);
#endif
- /*
- * If the port is in the process of being closed, just force
- * the transmit buffer to be empty, and let rp_close handle
- * the clean up.
- */
- if (info->flags & ROCKET_CLOSING) {
- cli();
- info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
- wake_up_interruptible(&tty->write_wait);
+ rp_flush_buffer(tty);
+ if (info->flags & ROCKET_CLOSING)
return;
- }
if (info->count) {
- rp_num_ports_open--;
+#if ((LINUX_VERSION_CODE < VERSION_CODE(2,5,0)) && defined(MODULE))
+ MOD_DEC_USE_COUNT;
+#endif
+ atomic_dec(&rp_num_ports_open);
}
-
- xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
+ clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
info->count = 0;
info->flags &= ~ROCKET_NORMAL_ACTIVE;
info->tty = 0;
@@ -1469,149 +1810,168 @@
cp = &info->channel;
sDisRxFIFO(cp);
sDisTransmit(cp);
- sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
+ sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
sDisCTSFlowCtl(cp);
sDisTxSoftFlowCtl(cp);
sClrTxXOFF(cp);
info->flags &= ~ROCKET_INITIALIZED;
-
+
wake_up_interruptible(&info->open_wait);
}
/*
- * The Rocketport write routines. The Rocketport driver uses a
- * double-buffering strategy, with the twist that if the in-memory CPU
- * buffer is empty, and there's space in the transmit FIFO, the
- * writing routines will write directly to transmit FIFO.
- *
- * This gets a little tricky, but I'm pretty sure I got it all right.
+ * Exception handler - write char routine. The RocketPort driver uses a
+ * double-buffering strategy, with the twist that if the in-memory CPU
+ * buffer is empty, and there's space in the transmit FIFO, the
+ * writing routines will write directly to transmit FIFO.
+ * Write buffer and counters protected by spinlocks
*/
static void rp_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
- CHANNEL_t *cp;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ CHANNEL_t *cp;
+ unsigned long flags;
- if (rocket_paranoia_check(info, tty->name, "rp_put_char"))
+ if (rocket_paranoia_check(info, "rp_put_char"))
return;
+ /* Grab the port write semaphore, locking out other processes that try to write to this port */
+ down(&info->write_sem);
+
#ifdef ROCKET_DEBUG_WRITE
- printk("rp_put_char %c...", ch);
+ printk(KERN_INFO "rp_put_char %c...", ch);
#endif
-
+
+ spin_lock_irqsave(&info->slock, flags);
cp = &info->channel;
if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
- if (tty->stopped || tty->hw_stopped ||
- info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
+ if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
info->xmit_buf[info->xmit_head++] = ch;
- info->xmit_head &= XMIT_BUF_SIZE-1;
+ info->xmit_head &= XMIT_BUF_SIZE - 1;
info->xmit_cnt++;
- xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
+ set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
} else {
sOutB(sGetTxRxDataIO(cp), ch);
info->xmit_fifo_room--;
}
+ spin_unlock_irqrestore(&info->slock, flags);
+ up(&info->write_sem);
}
-static int rp_write(struct tty_struct * tty, int from_user,
+/*
+ * Exception handler - write routine, called when user app writes to the device.
+ * A per port write semaphore is used to protect from another process writing to
+ * this port at the same time. This other process could be running on the other CPU
+ * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out).
+ * Spinlocks protect the info xmit members.
+ */
+static int rp_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
- CHANNEL_t *cp;
- const unsigned char *b;
- int c, retval = 0;
- unsigned long flags;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ CHANNEL_t *cp;
+ const unsigned char *b;
+ int c, retval = 0;
+ unsigned long flags;
- if (count <= 0 || rocket_paranoia_check(info, tty->name, "rp_write"))
+ if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
return 0;
+ down_interruptible(&info->write_sem);
+
#ifdef ROCKET_DEBUG_WRITE
- printk("rp_write %d chars...", count);
+ printk(KERN_INFO "rp_write %d chars...", count);
#endif
cp = &info->channel;
- if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
+ if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
- if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0
- && info->xmit_fifo_room >= 0) {
+ /*
+ * If the write queue for the port is empty, and there is FIFO space, stuff bytes
+ * into FIFO. Use the write queue for temp storage.
+ */
+ if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
c = MIN(count, info->xmit_fifo_room);
b = buf;
if (from_user) {
- down(&tmp_buf_sem);
- c -= copy_from_user(tmp_buf, buf, c);
- b = tmp_buf;
- up(&tmp_buf_sem);
- /* In case we got pre-empted */
- if (!c) {
+ if (copy_from_user(info->xmit_buf, buf, c)) {
retval = -EFAULT;
goto end;
}
if (info->tty == 0)
goto end;
+ b = info->xmit_buf;
c = MIN(c, info->xmit_fifo_room);
}
- sOutStrW(sGetTxRxDataIO(cp), b, c/2);
+
+ /* Push data into FIFO, 2 bytes at a time */
+ sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
+
+ /* If there is a byte remaining, write it */
if (c & 1)
- sOutB(sGetTxRxDataIO(cp), b[c-1]);
+ sOutB(sGetTxRxDataIO(cp), b[c - 1]);
+
retval += c;
buf += c;
count -= c;
+
+ spin_lock_irqsave(&info->slock, flags);
info->xmit_fifo_room -= c;
+ spin_unlock_irqrestore(&info->slock, flags);
}
+
+ /* If count is zero, we wrote it all and are done */
if (!count)
goto end;
-
- save_flags(flags);
+
+ /* Write remaining data into the port's xmit_buf */
while (1) {
- if (info->tty == 0) {
- restore_flags(flags);
+ if (info->tty == 0) /* Seemingly obligatory check... */
goto end;
- }
- c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
- XMIT_BUF_SIZE - info->xmit_head));
+
+ c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
if (c <= 0)
break;
b = buf;
if (from_user) {
- down(&tmp_buf_sem);
- c -= copy_from_user(tmp_buf, buf, c);
- b = tmp_buf;
- up(&tmp_buf_sem);
- if (!c) {
- if (retval == 0)
- retval = -EFAULT;
+ if (copy_from_user(info->xmit_buf + info->xmit_head, b, c)) {
+ retval = -EFAULT;
goto end_intr;
+ } else {
+ memcpy(info->xmit_buf + info->xmit_head, b, c);
}
- /* In case we got pre-empted */
- if (info->tty == 0)
- goto end_intr;
}
- cli();
- c = MIN(c, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
- XMIT_BUF_SIZE - info->xmit_head));
- memcpy(info->xmit_buf + info->xmit_head, b, c);
- info->xmit_head = (info->xmit_head + c) & (XMIT_BUF_SIZE-1);
+
+ spin_lock_irqsave(&info->slock, flags);
+ info->xmit_head =
+ (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
info->xmit_cnt += c;
- restore_flags(flags);
+ spin_unlock_irqrestore(&info->slock, flags);
+
buf += c;
count -= c;
retval += c;
}
+
end_intr:
if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
- xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
- restore_flags(flags);
+ set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
end:
- if (info->xmit_cnt < WAKEUP_CHARS) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
+ if (info->xmit_cnt < WAKEUP_CHARS) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
wake_up_interruptible(&tty->write_wait);
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+ wake_up_interruptible(&tty->poll_wait);
+#endif
}
+ up(&info->write_sem);
return retval;
}
@@ -1622,17 +1982,17 @@
*/
static int rp_write_room(struct tty_struct *tty)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
- int ret;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ int ret;
- if (rocket_paranoia_check(info, tty->name, "rp_write_room"))
+ if (rocket_paranoia_check(info, "rp_write_room"))
return 0;
ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
if (ret < 0)
ret = 0;
#ifdef ROCKET_DEBUG_WRITE
- printk("rp_write_room returns %d...", ret);
+ printk(KERN_INFO "rp_write_room returns %d...", ret);
#endif
return ret;
}
@@ -1643,332 +2003,655 @@
*/
static int rp_chars_in_buffer(struct tty_struct *tty)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
- CHANNEL_t *cp;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ CHANNEL_t *cp;
- if (rocket_paranoia_check(info, tty->name, "rp_chars_in_buffer"))
+ if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
return 0;
cp = &info->channel;
#ifdef ROCKET_DEBUG_WRITE
- printk("rp_chars_in_buffer returns %d...", info->xmit_cnt);
+ printk(KERN_INFO "rp_chars_in_buffer returns %d...", info->xmit_cnt);
#endif
return info->xmit_cnt;
}
+/*
+ * Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
+ * r_port struct for the port. Note that spinlock are used to protect info members,
+ * do not call this function if the spinlock is already held.
+ */
static void rp_flush_buffer(struct tty_struct *tty)
{
- struct r_port * info = (struct r_port *)tty->driver_data;
- CHANNEL_t *cp;
+ struct r_port *info = (struct r_port *) tty->driver_data;
+ CHANNEL_t *cp;
+ unsigned long flags;
- if (rocket_paranoia_check(info, tty->name, "rp_flush_buffer"))
+ if (rocket_paranoia_check(info, "rp_flush_buffer"))
return;
- cli();
+ spin_lock_irqsave(&info->slock, flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- sti();
+ spin_unlock_irqrestore(&info->slock, flags);
+
wake_up_interruptible(&tty->write_wait);
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
-
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+ wake_up_interruptible(&tty->poll_wait);
+#endif
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup) (tty);
+
cp = &info->channel;
-
sFlushTxFIFO(cp);
}
#ifdef CONFIG_PCI
-
-int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
+
+/*
+ * Called when a PCI card is found. Retrieves and stores model information,
+ * init's aiopic and serial port hardware.
+ * Inputs: i is the board number (0-n)
+ */
+__init int register_PCI(int i, struct pci_dev *dev)
{
- int num_aiops, aiop, max_num_aiops, num_chan, chan;
- unsigned int aiopio[MAX_AIOPS_PER_BOARD];
- char *str;
- CONTROLLER_t *ctlp;
- struct pci_dev *dev = pci_find_slot(bus, device_fn);
+ int num_aiops, aiop, max_num_aiops, num_chan, chan;
+ unsigned int aiopio[MAX_AIOPS_PER_BOARD];
+ char *str, *board_type;
+ CONTROLLER_t *ctlp;
- if (!dev)
+ int fast_clock = 0;
+ int altChanRingIndicator = 0;
+ int ports_per_aiop = 8;
+ int ret;
+ unsigned int class_rev;
+ WordIO_t ConfigIO = 0;
+ ByteIO_t UPCIRingInd = 0;
+
+ if (!dev || pci_enable_device(dev))
return 0;
- if (pci_enable_device(dev))
+ rcktpt_io_addr[i] = pci_resource_start(dev, 0);
+ ret = pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+
+ if (ret) {
+ printk(KERN_INFO " Error during register_PCI(), unable to read config dword \n");
return 0;
+ }
+
+ rcktpt_type[i] = ROCKET_TYPE_NORMAL;
+ rocketModel[i].loadrm2 = 0;
+ rocketModel[i].startingPortNumber = nextLineNumber;
- rcktpt_io_addr[i] = pci_resource_start (dev, 0);
- switch(dev->device) {
+ /* Depending on the model, set up some config variables */
+ switch (dev->device) {
case PCI_DEVICE_ID_RP4QUAD:
str = "Quadcable";
max_num_aiops = 1;
+ ports_per_aiop = 4;
+ rocketModel[i].model = MODEL_RP4QUAD;
+ strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
+ rocketModel[i].numPorts = 4;
break;
case PCI_DEVICE_ID_RP8OCTA:
str = "Octacable";
max_num_aiops = 1;
+ rocketModel[i].model = MODEL_RP8OCTA;
+ strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
+ rocketModel[i].numPorts = 8;
+ break;
+ case PCI_DEVICE_ID_URP8OCTA:
+ str = "Octacable";
+ max_num_aiops = 1;
+ rocketModel[i].model = MODEL_UPCI_RP8OCTA;
+ strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
+ rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP8INTF:
str = "8";
max_num_aiops = 1;
+ rocketModel[i].model = MODEL_RP8INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
+ rocketModel[i].numPorts = 8;
+ break;
+ case PCI_DEVICE_ID_URP8INTF:
+ str = "8";
+ max_num_aiops = 1;
+ rocketModel[i].model = MODEL_UPCI_RP8INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
+ rocketModel[i].numPorts = 8;
break;
case PCI_DEVICE_ID_RP8J:
str = "8J";
max_num_aiops = 1;
+ rocketModel[i].model = MODEL_RP8J;
+ strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
+ rocketModel[i].numPorts = 8;
+ break;
+ case PCI_DEVICE_ID_RP4J:
+ str = "4J";
+ max_num_aiops = 1;
+ ports_per_aiop = 4;
+ rocketModel[i].model = MODEL_RP4J;
+ strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
+ rocketModel[i].numPorts = 4;
+ break;
+ case PCI_DEVICE_ID_RP8SNI:
+ str = "8 (DB78 Custom)";
+ max_num_aiops = 1;
+ rocketModel[i].model = MODEL_RP8SNI;
+ strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
+ rocketModel[i].numPorts = 8;
+ break;
+ case PCI_DEVICE_ID_RP16SNI:
+ str = "16 (DB78 Custom)";
+ max_num_aiops = 2;
+ rocketModel[i].model = MODEL_RP16SNI;
+ strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
+ rocketModel[i].numPorts = 16;
+ break;
+ case PCI_DEVICE_ID_RP16INTF:
+ str = "16";
+ max_num_aiops = 2;
+ rocketModel[i].model = MODEL_RP16INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
+ rocketModel[i].numPorts = 16;
+ break;
+ case PCI_DEVICE_ID_URP16INTF:
+ str = "16";
+ max_num_aiops = 2;
+ rocketModel[i].model = MODEL_UPCI_RP16INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
+ rocketModel[i].numPorts = 16;
+ break;
+ case PCI_DEVICE_ID_CRP16INTF:
+ str = "16";
+ max_num_aiops = 2;
+ rocketModel[i].model = MODEL_CPCI_RP16INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
+ rocketModel[i].numPorts = 16;
+ break;
+ case PCI_DEVICE_ID_RP32INTF:
+ str = "32";
+ max_num_aiops = 4;
+ rocketModel[i].model = MODEL_RP32INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
+ rocketModel[i].numPorts = 32;
+ break;
+ case PCI_DEVICE_ID_URP32INTF:
+ str = "32";
+ max_num_aiops = 4;
+ rocketModel[i].model = MODEL_UPCI_RP32INTF;
+ strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
+ rocketModel[i].numPorts = 32;
+ break;
+ case PCI_DEVICE_ID_RPP4:
+ str = "Plus Quadcable";
+ max_num_aiops = 1;
+ ports_per_aiop = 4;
+ altChanRingIndicator++;
+ fast_clock++;
+ rocketModel[i].model = MODEL_RPP4;
+ strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
+ rocketModel[i].numPorts = 4;
+ break;
+ case PCI_DEVICE_ID_RPP8:
+ str = "Plus Octacable";
+ max_num_aiops = 2;
+ ports_per_aiop = 4;
+ altChanRingIndicator++;
+ fast_clock++;
+ rocketModel[i].model = MODEL_RPP8;
+ strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
+ rocketModel[i].numPorts = 8;
+ break;
+ case PCI_DEVICE_ID_RP2_232:
+ str = "Plus 2 (RS-232)";
+ max_num_aiops = 1;
+ ports_per_aiop = 2;
+ altChanRingIndicator++;
+ fast_clock++;
+ rocketModel[i].model = MODEL_RP2_232;
+ strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
+ rocketModel[i].numPorts = 2;
+ break;
+ case PCI_DEVICE_ID_RP2_422:
+ str = "Plus 2 (RS-422)";
+ max_num_aiops = 1;
+ ports_per_aiop = 2;
+ altChanRingIndicator++;
+ fast_clock++;
+ rocketModel[i].model = MODEL_RP2_422;
+ strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
+ rocketModel[i].numPorts = 2;
+ break;
+ case PCI_DEVICE_ID_RP6M:
+
+ max_num_aiops = 1;
+ ports_per_aiop = 6;
+ str = "6-port";
+
+ /* If class_rev is 1, the rocketmodem flash must be loaded. If it is 2 it is a "socketed" version. */
+ if ((class_rev & 0xFF) == 1) {
+ rcktpt_type[i] = ROCKET_TYPE_MODEMII;
+ rocketModel[i].loadrm2 = 1;
+ } else {
+ rcktpt_type[i] = ROCKET_TYPE_MODEM;
+ }
+
+ rocketModel[i].model = MODEL_RP6M;
+ strcpy(rocketModel[i].modelString, "RocketModem 6 port");
+ rocketModel[i].numPorts = 6;
+ break;
+ case PCI_DEVICE_ID_RP4M:
+ max_num_aiops = 1;
+ ports_per_aiop = 4;
+ str = "4-port";
+ if ((class_rev & 0xFF) == 1) {
+ rcktpt_type[i] = ROCKET_TYPE_MODEMII;
+ rocketModel[i].loadrm2 = 1;
+ } else {
+ rcktpt_type[i] = ROCKET_TYPE_MODEM;
+ }
+
+ rocketModel[i].model = MODEL_RP4M;
+ strcpy(rocketModel[i].modelString, "RocketModem 4 port");
+ rocketModel[i].numPorts = 4;
break;
- case PCI_DEVICE_ID_RP16INTF:
- str = "16";
- max_num_aiops = 2;
+ default:
+ str = "(unknown/unsupported)";
+ max_num_aiops = 0;
break;
- case PCI_DEVICE_ID_RP32INTF:
- str = "32";
- max_num_aiops = 4;
+ }
+
+ /*
+ * Check for UPCI boards.
+ */
+
+ switch (dev->device) {
+ case PCI_DEVICE_ID_URP32INTF:
+ case PCI_DEVICE_ID_URP8INTF:
+ case PCI_DEVICE_ID_URP16INTF:
+ case PCI_DEVICE_ID_CRP16INTF:
+ case PCI_DEVICE_ID_URP8OCTA:
+ rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+ ConfigIO = pci_resource_start(dev, 1);
+ if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
+ UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+
+ /*
+ * Check for octa or quad cable.
+ */
+ if (!
+ (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
+ PCI_GPIO_CTRL_8PORT)) {
+ str = "Quadcable";
+ ports_per_aiop = 4;
+ rocketModel[i].numPorts = 4;
+ }
+ }
break;
- case PCI_DEVICE_ID_RPP4:
- str = "Plus Quadcable";
+ case PCI_DEVICE_ID_UPCI_RM3_8PORT:
+ str = "8 ports";
max_num_aiops = 1;
+ rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
+ strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
+ rocketModel[i].numPorts = 8;
+ rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+ UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+ ConfigIO = pci_resource_start(dev, 1);
+ rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
break;
- case PCI_DEVICE_ID_RPP8:
- str = "Plus Octacable";
+ case PCI_DEVICE_ID_UPCI_RM3_4PORT:
+ str = "4 ports";
max_num_aiops = 1;
+ rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
+ strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
+ rocketModel[i].numPorts = 4;
+ rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+ UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+ ConfigIO = pci_resource_start(dev, 1);
+ rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
break;
- case PCI_DEVICE_ID_RP8M:
- str = "8-port Modem";
- max_num_aiops = 1;
+ default:
break;
- case 0x8:
- str = "mysterious 8 port";
- max_num_aiops = 1;
+ }
+
+ switch (rcktpt_type[i]) {
+ case ROCKET_TYPE_MODEM:
+ board_type = "RocketModem";
+ break;
+ case ROCKET_TYPE_MODEMII:
+ board_type = "RocketModem II";
+ break;
+ case ROCKET_TYPE_MODEMIII:
+ board_type = "RocketModem III";
break;
default:
- str = "(unknown/unsupported)";
- max_num_aiops = 0;
+ board_type = "RocketPort";
break;
}
- for(aiop=0;aiop < max_num_aiops;aiop++)
+
+ if (fast_clock) {
+ sClockPrescale = 0x12; /* mod 2 (divide by 3) */
+ rp_baud_base[i] = 921600;
+ } else {
+ /*
+ * If support_low_speed is set, use the slow clock
+ * prescale, which supports 50 bps
+ */
+ if (support_low_speed) {
+ /* mod 9 (divide by 10) prescale */
+ sClockPrescale = 0x19;
+ rp_baud_base[i] = 230400;
+ } else {
+ /* mod 4 (devide by 5) prescale */
+ sClockPrescale = 0x14;
+ rp_baud_base[i] = 460800;
+ }
+ }
+
+ for (aiop = 0; aiop < max_num_aiops; aiop++)
aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
ctlp = sCtlNumToCtlPtr(i);
- num_aiops = sPCIInitController(ctlp, i,
- aiopio, max_num_aiops, 0,
- FREQ_DIS, 0);
- printk("Rocketport controller #%d found at %02x:%02x, "
- "%d AIOP(s) (PCI Rocketport %s)\n", i, bus, device_fn,
- num_aiops, str);
- if(num_aiops <= 0) {
+ num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
+ for (aiop = 0; aiop < max_num_aiops; aiop++)
+ ctlp->AiopNumChan[aiop] = ports_per_aiop;
+
+#if LINUX_VERSION_CODE < VERSION_CODE(2,3,99)
+ printk(KERN_INFO "Comtrol PCI controller #%d ID 0x%x found at 0x%lx, "
+ "%d AIOP(s) (%s)\n", i, dev->device, rcktpt_io_addr[i],
+ num_aiops, rocketModel[i].modelString);
+#else
+ printk
+ ("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, "
+ "%d AIOP(s) (%s)\n", i, dev->device, dev->slot_name,
+ rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString);
+#endif
+
+ printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
+ rocketModel[i].modelString,
+ rocketModel[i].startingPortNumber,
+ rocketModel[i].startingPortNumber +
+ rocketModel[i].numPorts - 1);
+
+ if (num_aiops <= 0) {
rcktpt_io_addr[i] = 0;
- return(0);
+ return (0);
}
- for(aiop = 0;aiop < num_aiops; aiop++) {
+ is_PCI[i] = 1;
+
+ /* Reset the AIOPIC, init the serial ports */
+ for (aiop = 0; aiop < num_aiops; aiop++) {
sResetAiopByNum(ctlp, aiop);
- sEnAiop(ctlp, aiop);
- num_chan = sGetAiopNumChan(ctlp, aiop);
- for(chan=0;chan < num_chan; chan++)
- init_r_port(i, aiop, chan);
+ num_chan = ports_per_aiop;
+ for (chan = 0; chan < num_chan; chan++)
+ init_r_port(i, aiop, chan, dev);
+ }
+
+ /* Rocket modems must be reset */
+ if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
+ (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
+ (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
+ num_chan = ports_per_aiop;
+ for (chan = 0; chan < num_chan; chan++)
+ sPCIModemReset(ctlp, chan, 1);
+ mdelay(500);
+ for (chan = 0; chan < num_chan; chan++)
+ sPCIModemReset(ctlp, chan, 0);
+ mdelay(500);
+ rmSpeakerReset(ctlp, rocketModel[i].model);
}
- return(1);
+ return (1);
}
+#if LINUX_VERSION_CODE > VERSION_CODE(2,3,99) /* Linux version 2.4 and greater */
+
+
+/*
+ * Probes for PCI cards, inits them if found
+ * Input: board_found = number of ISA boards already found, or the
+ * starting board number
+ * Returns: Number of PCI boards found
+ */
static int __init init_PCI(int boards_found)
{
- unsigned char bus, device_fn;
- int i, count = 0;
+ struct pci_dev *dev = NULL;
+ int count = 0;
- for(i=0; i < (NUM_BOARDS - boards_found); i++) {
- if (!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn))
- if (register_PCI(count+boards_found, bus, device_fn))
- count++;
- if (!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP8J, i, &bus, &device_fn))
- if (register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP8OCTA, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP8INTF, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP16INTF, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP32INTF, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP8J, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RPP4, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RPP8, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- PCI_DEVICE_ID_RP8M, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
- if(!pcibios_find_device(PCI_VENDOR_ID_RP,
- 0x8, i, &bus, &device_fn))
- if(register_PCI(count+boards_found, bus, device_fn))
- count++;
+ /* Work through the PCI device list, pulling out ours */
+ while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
+ if (register_PCI(count + boards_found, dev))
+ count++;
}
- return(count);
+ return (count);
+}
+
+#else /* Linux version 2.2 */
+
+/*
+ * Linux 2.2 pci_find_device() does not allow a search of all devices for a certain vendor,
+ * you have to try each device ID. Comtrol device ID's are 0x0000 -0x000F for the original
+ * boards. Newer board are 0x08xx (see upci_ids[]).
+ */
+static int __init init_PCI(int boards_found)
+{
+ int j, count = 0;
+ struct pci_dev *dev = NULL;
+
+ static int upci_ids[] = {
+ PCI_DEVICE_ID_URP32INTF,
+ PCI_DEVICE_ID_URP8INTF,
+ PCI_DEVICE_ID_URP16INTF,
+ PCI_DEVICE_ID_CRP16INTF,
+ PCI_DEVICE_ID_URP8OCTA,
+ PCI_DEVICE_ID_UPCI_RM3_8PORT,
+ PCI_DEVICE_ID_UPCI_RM3_4PORT
+ };
+
+#define NUM_UPCI_IDS (sizeof(upci_ids) / sizeof(upci_ids[0]))
+
+ /* Try finding devices with PCI ID's 0x0000 - 0x000F */
+ for (j = 0; j < 16; j++) {
+ while ((dev = pci_find_device(PCI_VENDOR_ID_RP, j, dev))) {
+ register_PCI(count + boards_found, dev);
+ count++;
+ }
+ }
+
+ /* Now try finding the UPCI devices, which have PCI ID's 0x0800 - 0x080F */
+ for (j = 0; j < NUM_UPCI_IDS; j++) {
+ while ((dev =
+ pci_find_device(PCI_VENDOR_ID_RP, upci_ids[j], dev))) {
+ register_PCI(count + boards_found, dev);
+ count++;
+ }
+ }
+ return (count);
}
-#endif
+#endif /* Linux version 2.2/2.4 */
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Probes for ISA cards
+ * Input: i = the board number to look for
+ * Returns: 1 if board found, 0 else
+ */
static int __init init_ISA(int i, int *reserved_controller)
{
- int num_aiops, num_chan;
- int aiop, chan;
- int extent = 0;
- unsigned int aiopio[MAX_AIOPS_PER_BOARD];
- CONTROLLER_t *ctlp;
+ int num_aiops, num_chan = 0, total_num_chan = 0;
+ int aiop, chan;
+ unsigned int aiopio[MAX_AIOPS_PER_BOARD];
+ CONTROLLER_t *ctlp;
+ char *type_string;
- if (rcktpt_io_addr[i] == 0)
- return(0);
+ if (rcktpt_io_addr[i] == 0 || controller == 0)
+ return (0);
+ if (check_region(rcktpt_io_addr[i], 64)) {
+ printk(KERN_INFO "RocketPort board address 0x%lx in use...\n", rcktpt_io_addr[i]);
+ rcktpt_io_addr[i] = 0;
+ return (0);
+ }
if (rcktpt_io_addr[i] + 0x40 == controller) {
*reserved_controller = 1;
- extent = 68;
+ request_region(rcktpt_io_addr[i], 68, "Comtrol RocketPort");
} else {
- extent = 64;
+ request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort");
}
- if (!request_region(rcktpt_io_addr[i], extent,
- "Comtrol Rocketport")) {
- printk("RocketPort board address 0x%lx in use...\n",
- rcktpt_io_addr[i]);
- rcktpt_io_addr[i] = 0;
- return(0);
+
+ ctlp = sCtlNumToCtlPtr(i);
+
+ ctlp->boardType = rcktpt_type[i];
+
+ switch (rcktpt_type[i]) {
+ case ROCKET_TYPE_PC104:
+ type_string = "(PC104)";
+ break;
+ case ROCKET_TYPE_MODEM:
+ type_string = "(RocketModem)";
+ break;
+ case ROCKET_TYPE_MODEMII:
+ type_string = "(RocketModem II)";
+ break;
+ default:
+ type_string = "";
+ break;
}
-
- for (aiop=0; aiopboardType == ROCKET_TYPE_PC104) {
+ sEnAiop(ctlp, 2); /* only one AIOPIC, but these */
+ sEnAiop(ctlp, 3); /* CSels used for other stuff */
+ }
+
if (num_aiops <= 0) {
- release_region(rcktpt_io_addr[i], extent);
+ if (rcktpt_io_addr[i] + 0x40 == controller) {
+ *reserved_controller = 0;
+ release_region(rcktpt_io_addr[i], 68);
+ } else {
+ release_region(rcktpt_io_addr[i], 64);
+ }
rcktpt_io_addr[i] = 0;
- return(0);
+ return (0);
}
for (aiop = 0; aiop < num_aiops; aiop++) {
sResetAiopByNum(ctlp, aiop);
sEnAiop(ctlp, aiop);
- num_chan = sGetAiopNumChan(ctlp,aiop);
- for (chan=0; chan < num_chan; chan++)
- init_r_port(i, aiop, chan);
- }
- printk("Rocketport controller #%d found at 0x%lx, "
- "%d AIOPs\n", i, rcktpt_io_addr[i],
- num_aiops);
- return(1);
-}
+ num_chan = sGetAiopNumChan(ctlp, aiop);
+ total_num_chan += num_chan;
+ for (chan = 0; chan < num_chan; chan++)
+ init_r_port(i, aiop, chan, NULL);
+ }
+ is_PCI[i] = 0;
+ if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
+ num_chan = sGetAiopNumChan(ctlp, 0);
+ total_num_chan = num_chan;
+ for (chan = 0; chan < num_chan; chan++)
+ sModemReset(ctlp, chan, 1);
+ mdelay(500);
+ for (chan = 0; chan < num_chan; chan++)
+ sModemReset(ctlp, chan, 0);
+ mdelay(500);
+ strcpy(rocketModel[i].modelString, "RocketModem ISA");
+ } else {
+ strcpy(rocketModel[i].modelString, "RocketPort ISA");
+ }
+ rocketModel[i].numPorts = total_num_chan;
+ rocketModel[i].model = MODEL_ISA;
+
+ printk(KERN_INFO "Comtrol ISA controller #%d found at 0x%lx, "
+ "%d AIOPs %s\n", i, rcktpt_io_addr[i], num_aiops,
+ type_string);
+ printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
+ rocketModel[i].modelString,
+ rocketModel[i].startingPortNumber,
+ rocketModel[i].startingPortNumber +
+ rocketModel[i].numPorts - 1);
+ return (1);
+}
/*
* The module "startup" routine; it's run when the module is loaded.
*/
int __init rp_init(void)
{
- int i, retval, pci_boards_found, isa_boards_found;
- int reserved_controller = 0;
+ int retval, pci_boards_found, isa_boards_found, i;
+ int reserved_controller = 0;
- printk("Rocketport device driver module, version %s, %s\n",
+ printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
ROCKET_VERSION, ROCKET_DATE);
/*
- * Set up the timer channel. If it is already in use by
- * some other driver, give up.
+ * Set up the timer channel.
*/
- if (rocket_timer.function) {
- printk("rocket.o: Timer already in use!\n");
- return -EBUSY;
- }
init_timer(&rocket_timer);
rocket_timer.function = rp_do_poll;
-
+
/*
* Initialize the array of pointers to our own internal state
* structures.
*/
- memset(rp_table, 0, sizeof(rp_table));
- memset(xmit_flags, 0, sizeof(xmit_flags));
+ memset(rp_table, 0, sizeof (rp_table));
+ memset(xmit_flags, 0, sizeof (xmit_flags));
+
+ for (i = 0; i < MAX_RP_PORTS; i++)
+ lineNumbers[i] = 0;
+ nextLineNumber = 0;
+ memset(rocketModel, 0, sizeof (rocketModel));
- if (board1 == 0)
- board1 = 0x180;
- if (controller == 0)
+ if (board1 && controller == 0)
controller = board1 + 0x40;
- if (check_region(controller, 4)) {
- printk("Controller IO addresses in use, unloading driver.\n");
+ if (controller && check_region(controller, 4)) {
+ printk(KERN_INFO "Controller IO addresses in use, unloading driver.\n");
return -EBUSY;
}
-
+
+ /* Store ISA variable retrieved from command line or .conf file. */
rcktpt_io_addr[0] = board1;
rcktpt_io_addr[1] = board2;
rcktpt_io_addr[2] = board3;
rcktpt_io_addr[3] = board4;
- /*
- * If support_low_speed is set, use the slow clock prescale,
- * which supports 50 bps
- */
- if (support_low_speed) {
- sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
- rp_baud_base = 230400;
- } else {
- sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
- rp_baud_base = 460800;
- }
-
- /*
- * OK, let's probe each of the controllers looking for boards.
- */
- isa_boards_found = 0;
- pci_boards_found = 0;
- for (i=0; i < NUM_BOARDS; i++) {
- if(init_ISA(i, &reserved_controller))
- isa_boards_found++;
- }
-#ifdef CONFIG_PCI
- if (pci_present()) {
- if(isa_boards_found < NUM_BOARDS)
- pci_boards_found = init_PCI(isa_boards_found);
- } else {
- printk("No PCI BIOS found\n");
- }
-#endif
- max_board = pci_boards_found + isa_boards_found;
-
- if (max_board == 0) {
- printk("No rocketport ports found; unloading driver.\n");
- rocket_timer.function = 0;
- return -ENODEV;
- }
-
- if (reserved_controller == 0)
- request_region(controller, 4, "Comtrol Rocketport");
+ rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+ rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
+ rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+ rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
+ rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+ rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
+ rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+ rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
/*
* Set up the tty driver structure and then register this
* driver with the tty layer.
*/
- memset(&rocket_driver, 0, sizeof(struct tty_driver));
+ memset(&rocket_driver, 0, sizeof (struct tty_driver));
rocket_driver.magic = TTY_DRIVER_MAGIC;
- rocket_driver.owner = THIS_MODULE;
-#ifdef CONFIG_DEVFS_FS
- rocket_driver.name = "tts/R";
-#else
+ rocket_driver.flags = TTY_DRIVER_NO_DEVFS;
rocket_driver.name = "ttyR";
-#endif
+ rocket_driver.driver_name = "Comtrol RocketPort";
rocket_driver.major = TTY_ROCKET_MAJOR;
rocket_driver.minor_start = 0;
rocket_driver.num = MAX_RP_PORTS;
@@ -1976,8 +2659,10 @@
rocket_driver.subtype = SERIAL_TYPE_NORMAL;
rocket_driver.init_termios = tty_std_termios;
rocket_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- rocket_driver.flags = TTY_DRIVER_REAL_RAW;
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+#ifdef ROCKET_SOFT_FLOW
+ rocket_driver.flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+#endif
rocket_driver.refcount = &rocket_refcount;
rocket_driver.table = rocket_table;
rocket_driver.termios = rocket_termios;
@@ -2001,58 +2686,93 @@
rocket_driver.send_xchar = rp_send_xchar;
rocket_driver.wait_until_sent = rp_wait_until_sent;
+#if (LINUX_VERSION_CODE > VERSION_CODE(2,5,0))
+ rocket_driver.owner = THIS_MODULE;
+ rocket_driver.tiocmget = rp_tiocmget;
+ rocket_driver.tiocmset = rp_tiocmset;
+#endif /* Kernel > 2.5 */
+
retval = tty_register_driver(&rocket_driver);
if (retval < 0) {
- printk("Couldn't install tty Rocketport driver "
- "(error %d)\n", -retval);
- release_region(controller, 4);
+ printk(KERN_INFO "Couldn't install tty RocketPort driver (error %d)\n", -retval);
return -1;
}
+
#ifdef ROCKET_DEBUG_OPEN
- printk("Rocketport driver is major %d\n",
- rocket_driver.major);
+ printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
+#endif
+
+ /*
+ * OK, let's probe each of the controllers looking for boards. Any boards found
+ * will be initialized here.
+ */
+ isa_boards_found = 0;
+ pci_boards_found = 0;
+
+ for (i = 0; i < NUM_BOARDS; i++) {
+ if (init_ISA(i, &reserved_controller))
+ isa_boards_found++;
+ }
+
+#ifdef CONFIG_PCI
+ if (pci_present()) {
+ if (isa_boards_found < NUM_BOARDS)
+ pci_boards_found = init_PCI(isa_boards_found);
+ } else {
+ printk(KERN_INFO "No PCI BIOS found\n");
+ }
#endif
+ max_board = pci_boards_found + isa_boards_found;
+
+ if (max_board == 0) {
+ printk(KERN_INFO "No rocketport ports found; unloading driver.\n");
+ del_timer_sync(&rocket_timer);
+ return -ENXIO;
+ }
+
+ if (isa_boards_found) {
+ if (reserved_controller == 0)
+ request_region(controller, 4, "Comtrol RocketPort");
+ } else {
+ controller = 0;
+ }
+
return 0;
}
#ifdef MODULE
-int init_module(void)
-{
- return rp_init();
-}
-void
-cleanup_module( void) {
- int retval;
- int i;
- int released_controller = 0;
+static void rp_cleanup_module(void)
+{
+ int retval;
+ int i;
+ int released_controller = 0;
del_timer_sync(&rocket_timer);
retval = tty_unregister_driver(&rocket_driver);
- if (retval) {
- printk("Error %d while trying to unregister "
+ if (retval)
+ printk(KERN_INFO "Error %d while trying to unregister "
"rocketport driver\n", -retval);
- }
+
for (i = 0; i < MAX_RP_PORTS; i++) {
if (rp_table[i])
kfree(rp_table[i]);
}
- for (i=0; i < NUM_BOARDS; i++) {
- if (rcktpt_io_addr[i] <= 0)
+
+ for (i = 0; i < NUM_BOARDS; i++) {
+ if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
continue;
if (rcktpt_io_addr[i] + 0x40 == controller) {
released_controller++;
release_region(rcktpt_io_addr[i], 68);
- } else
+ } else {
release_region(rcktpt_io_addr[i], 64);
- if (released_controller == 0)
- release_region(controller, 4);
+ }
}
- if (tmp_buf)
- free_page((unsigned long) tmp_buf);
- rocket_timer.function = 0;
+ if (controller && released_controller == 0)
+ release_region(controller, 4);
}
#endif
@@ -2088,69 +2808,60 @@
#define FALSE 0
#endif
-static Byte_t RData[RDATASIZE] =
-{
- 0x00, 0x09, 0xf6, 0x82,
- 0x02, 0x09, 0x86, 0xfb,
- 0x04, 0x09, 0x00, 0x0a,
- 0x06, 0x09, 0x01, 0x0a,
- 0x08, 0x09, 0x8a, 0x13,
- 0x0a, 0x09, 0xc5, 0x11,
- 0x0c, 0x09, 0x86, 0x85,
- 0x0e, 0x09, 0x20, 0x0a,
- 0x10, 0x09, 0x21, 0x0a,
- 0x12, 0x09, 0x41, 0xff,
- 0x14, 0x09, 0x82, 0x00,
- 0x16, 0x09, 0x82, 0x7b,
- 0x18, 0x09, 0x8a, 0x7d,
- 0x1a, 0x09, 0x88, 0x81,
- 0x1c, 0x09, 0x86, 0x7a,
- 0x1e, 0x09, 0x84, 0x81,
- 0x20, 0x09, 0x82, 0x7c,
- 0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE]=
-{
- 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
- 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
- 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
- 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
- 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
- 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
- 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
- 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
- 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
- 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
- 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
- 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
- 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
+static Byte_t RData[RDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82,
+ 0x02, 0x09, 0x86, 0xfb,
+ 0x04, 0x09, 0x00, 0x0a,
+ 0x06, 0x09, 0x01, 0x0a,
+ 0x08, 0x09, 0x8a, 0x13,
+ 0x0a, 0x09, 0xc5, 0x11,
+ 0x0c, 0x09, 0x86, 0x85,
+ 0x0e, 0x09, 0x20, 0x0a,
+ 0x10, 0x09, 0x21, 0x0a,
+ 0x12, 0x09, 0x41, 0xff,
+ 0x14, 0x09, 0x82, 0x00,
+ 0x16, 0x09, 0x82, 0x7b,
+ 0x18, 0x09, 0x8a, 0x7d,
+ 0x1a, 0x09, 0x88, 0x81,
+ 0x1c, 0x09, 0x86, 0x7a,
+ 0x1e, 0x09, 0x84, 0x81,
+ 0x20, 0x09, 0x82, 0x7c,
+ 0x22, 0x09, 0x0a, 0x0a
};
-CONTROLLER_T sController[CTL_SIZE] =
-{
- {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
- {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
- {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
- {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
+static Byte_t RRegData[RREGDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
+ 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
+ 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
+ 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
+ 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
+ 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
+ 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
+ 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
+ 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
+ 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
+ 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
+ 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
+ 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
};
-#if 0
-/* IRQ number to MUDBAC register 2 mapping */
-Byte_t sIRQMap[16] =
-{
- 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
+CONTROLLER_T sController[CTL_SIZE] = {
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
};
-#endif
-Byte_t sBitMapClrTbl[8] =
-{
- 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
+Byte_t sBitMapClrTbl[8] = {
+ 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
};
-Byte_t sBitMapSetTbl[8] =
-{
- 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
+Byte_t sBitMapSetTbl[8] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};
int sClockPrescale = 0x14;
@@ -2225,76 +2936,68 @@
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sInitController( CONTROLLER_T *CtlP,
- int CtlNum,
- ByteIO_t MudbacIO,
- ByteIO_t *AiopIOList,
- int AiopIOListSize,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly)
-{
- int i;
- ByteIO_t io;
-
- CtlP->CtlNum = CtlNum;
- CtlP->CtlID = CTLID_0001; /* controller release 1 */
- CtlP->BusType = isISA;
- CtlP->MBaseIO = MudbacIO;
- CtlP->MReg1IO = MudbacIO + 1;
- CtlP->MReg2IO = MudbacIO + 2;
- CtlP->MReg3IO = MudbacIO + 3;
+int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum,
+ Byte_t Frequency, int PeriodicOnly)
+{
+ int i;
+ ByteIO_t io;
+ int done;
+
+ CtlP->AiopIntrBits = aiop_intr_bits;
+ CtlP->AltChanRingIndicator = 0;
+ CtlP->CtlNum = CtlNum;
+ CtlP->CtlID = CTLID_0001; /* controller release 1 */
+ CtlP->BusType = isISA;
+ CtlP->MBaseIO = MudbacIO;
+ CtlP->MReg1IO = MudbacIO + 1;
+ CtlP->MReg2IO = MudbacIO + 2;
+ CtlP->MReg3IO = MudbacIO + 3;
#if 1
- CtlP->MReg2 = 0; /* interrupt disable */
- CtlP->MReg3 = 0; /* no periodic interrupts */
+ CtlP->MReg2 = 0; /* interrupt disable */
+ CtlP->MReg3 = 0; /* no periodic interrupts */
#else
- if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */
- {
- CtlP->MReg2 = 0; /* interrupt disable */
- CtlP->MReg3 = 0; /* no periodic interrupts */
- }
- else
- {
- CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
- CtlP->MReg3 = Frequency; /* set frequency */
- if(PeriodicOnly) /* periodic interrupt only */
- {
- CtlP->MReg3 |= PERIODIC_ONLY;
- }
- }
-#endif
- sOutB(CtlP->MReg2IO,CtlP->MReg2);
- sOutB(CtlP->MReg3IO,CtlP->MReg3);
- sControllerEOI(CtlP); /* clear EOI if warm init */
- /* Init AIOPs */
- CtlP->NumAiop = 0;
- for(i=0; i < AiopIOListSize; i++)
- {
- io = AiopIOList[i];
- CtlP->AiopIO[i] = (WordIO_t)io;
- CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
- sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
- sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
- sEnAiop(CtlP,i); /* enable the AIOP */
-
- CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
- if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
- {
- sDisAiop(CtlP,i); /* disable AIOP */
- break; /* done looking for AIOPs */
- }
-
- CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
- sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
- sOutB(io + _INDX_DATA,sClockPrescale);
- CtlP->NumAiop++; /* bump count of AIOPs */
- sDisAiop(CtlP,i); /* disable AIOP */
- }
-
- if(CtlP->NumAiop == 0)
- return(-1);
- else
- return(CtlP->NumAiop);
+ if (sIRQMap[IRQNum] == 0) { /* interrupts globally disabled */
+ CtlP->MReg2 = 0; /* interrupt disable */
+ CtlP->MReg3 = 0; /* no periodic interrupts */
+ } else {
+ CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */
+ CtlP->MReg3 = Frequency; /* set frequency */
+ if (PeriodicOnly) { /* periodic interrupt only */
+ CtlP->MReg3 |= PERIODIC_ONLY;
+ }
+ }
+#endif
+ sOutB(CtlP->MReg2IO, CtlP->MReg2);
+ sOutB(CtlP->MReg3IO, CtlP->MReg3);
+ sControllerEOI(CtlP); /* clear EOI if warm init */
+ /* Init AIOPs */
+ CtlP->NumAiop = 0;
+ for (i = done = 0; i < AiopIOListSize; i++) {
+ io = AiopIOList[i];
+ CtlP->AiopIO[i] = (WordIO_t) io;
+ CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
+ sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03)); /* AIOP index */
+ sOutB(MudbacIO, (Byte_t) (io >> 6)); /* set up AIOP I/O in MUDBAC */
+ if (done)
+ continue;
+ sEnAiop(CtlP, i); /* enable the AIOP */
+ CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
+ if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
+ done = 1; /* done looking for AIOPs */
+ else {
+ CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
+ sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
+ sOutB(io + _INDX_DATA, sClockPrescale);
+ CtlP->NumAiop++; /* bump count of AIOPs */
+ }
+ sDisAiop(CtlP, i); /* disable AIOP */
+ }
+
+ if (CtlP->NumAiop == 0)
+ return (-1);
+ else
+ return (CtlP->NumAiop);
}
/***************************************************************************
@@ -2366,46 +3069,55 @@
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sPCIInitController( CONTROLLER_T *CtlP,
- int CtlNum,
- ByteIO_t *AiopIOList,
- int AiopIOListSize,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly)
-{
- int i;
- ByteIO_t io;
-
- CtlP->CtlNum = CtlNum;
- CtlP->CtlID = CTLID_0001; /* controller release 1 */
- CtlP->BusType = isPCI; /* controller release 1 */
-
- CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
-
- sPCIControllerEOI(CtlP); /* clear EOI if warm init */
- /* Init AIOPs */
- CtlP->NumAiop = 0;
- for(i=0; i < AiopIOListSize; i++)
- {
- io = AiopIOList[i];
- CtlP->AiopIO[i] = (WordIO_t)io;
- CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-
- CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
- if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
- break; /* done looking for AIOPs */
-
- CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
- sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */
- sOutB(io + _INDX_DATA,sClockPrescale);
- CtlP->NumAiop++; /* bump count of AIOPs */
- }
-
- if(CtlP->NumAiop == 0)
- return(-1);
- else
- return(CtlP->NumAiop);
+int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+ int PeriodicOnly, int altChanRingIndicator,
+ int UPCIRingInd)
+{
+ int i;
+ ByteIO_t io;
+
+ CtlP->AltChanRingIndicator = altChanRingIndicator;
+ CtlP->UPCIRingInd = UPCIRingInd;
+ CtlP->CtlNum = CtlNum;
+ CtlP->CtlID = CTLID_0001; /* controller release 1 */
+ CtlP->BusType = isPCI; /* controller release 1 */
+
+ if (ConfigIO) {
+ CtlP->isUPCI = 1;
+ CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
+ CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
+ CtlP->AiopIntrBits = upci_aiop_intr_bits;
+ } else {
+ CtlP->isUPCI = 0;
+ CtlP->PCIIO =
+ (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
+ CtlP->AiopIntrBits = aiop_intr_bits;
+ }
+
+ sPCIControllerEOI(CtlP); /* clear EOI if warm init */
+ /* Init AIOPs */
+ CtlP->NumAiop = 0;
+ for (i = 0; i < AiopIOListSize; i++) {
+ io = AiopIOList[i];
+ CtlP->AiopIO[i] = (WordIO_t) io;
+ CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
+
+ CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
+ if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
+ break; /* done looking for AIOPs */
+
+ CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
+ sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
+ sOutB(io + _INDX_DATA, sClockPrescale);
+ CtlP->NumAiop++; /* bump count of AIOPs */
+ }
+
+ if (CtlP->NumAiop == 0)
+ return (-1);
+ else
+ return (CtlP->NumAiop);
}
/***************************************************************************
@@ -2421,15 +3133,15 @@
*/
int sReadAiopID(ByteIO_t io)
{
- Byte_t AiopID; /* ID byte from AIOP */
+ Byte_t AiopID; /* ID byte from AIOP */
- sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */
- sOutB(io + _CMD_REG,0x0);
- AiopID = sInB(io + _CHN_STAT0) & 0x07;
- if(AiopID == 0x06)
- return(1);
- else /* AIOP does not exist */
- return(-1);
+ sOutB(io + _CMD_REG, RESET_ALL); /* reset AIOP */
+ sOutB(io + _CMD_REG, 0x0);
+ AiopID = sInW(io + _CHN_STAT0) & 0x07;
+ if (AiopID == 0x06)
+ return (1);
+ else /* AIOP does not exist */
+ return (-1);
}
/***************************************************************************
@@ -2447,16 +3159,18 @@
*/
int sReadAiopNumChan(WordIO_t io)
{
- Word_t x;
+ Word_t x;
+ static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
- sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
- sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */
- x = sInW(io + _INDX_DATA);
- sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */
- if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
- return(8);
- else
- return(4);
+ /* write to chan 0 SRAM */
+ sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0]));
+ sOutW(io + _INDX_ADDR, 0); /* read from SRAM, chan 0 */
+ x = sInW(io + _INDX_DATA);
+ sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
+ if (x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */
+ return (8);
+ else
+ return (4);
}
/***************************************************************************
@@ -2474,138 +3188,134 @@
No context switches are allowed while executing this function.
*/
-int sInitChan( CONTROLLER_T *CtlP,
- CHANNEL_T *ChP,
- int AiopNum,
- int ChanNum)
-{
- int i;
- WordIO_t AiopIO;
- WordIO_t ChIOOff;
- Byte_t *ChR;
- Word_t ChOff;
- static Byte_t R[4];
- int brd9600;
-
- if(ChanNum >= CtlP->AiopNumChan[AiopNum])
- return(FALSE); /* exceeds num chans in AIOP */
-
- /* Channel, AIOP, and controller identifiers */
- ChP->CtlP = CtlP;
- ChP->ChanID = CtlP->AiopID[AiopNum];
- ChP->AiopNum = AiopNum;
- ChP->ChanNum = ChanNum;
-
- /* Global direct addresses */
- AiopIO = CtlP->AiopIO[AiopNum];
- ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
- ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
- ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
- ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
- ChP->IndexData = AiopIO + _INDX_DATA;
-
- /* Channel direct addresses */
- ChIOOff = AiopIO + ChP->ChanNum * 2;
- ChP->TxRxData = ChIOOff + _TD0;
- ChP->ChanStat = ChIOOff + _CHN_STAT0;
- ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
- ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
-
- /* Initialize the channel from the RData array */
- for(i=0; i < RDATASIZE; i+=4)
- {
- R[0] = RData[i];
- R[1] = RData[i+1] + 0x10 * ChanNum;
- R[2] = RData[i+2];
- R[3] = RData[i+3];
- sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
- }
-
- ChR = ChP->R;
- for(i=0; i < RREGDATASIZE; i+=4)
- {
- ChR[i] = RRegData[i];
- ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
- ChR[i+2] = RRegData[i+2];
- ChR[i+3] = RRegData[i+3];
- }
-
- /* Indexed registers */
- ChOff = (Word_t)ChanNum * 0x1000;
-
- if (sClockPrescale == 0x14)
- brd9600 = 47;
- else
- brd9600 = 23;
-
- ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
- ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
- ChP->BaudDiv[2] = (Byte_t)brd9600;
- ChP->BaudDiv[3] = (Byte_t)(brd9600 >> 8);
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
-
- ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
- ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
- ChP->TxControl[2] = 0;
- ChP->TxControl[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
-
- ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
- ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
- ChP->RxControl[2] = 0;
- ChP->RxControl[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
-
- ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
- ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
- ChP->TxEnables[2] = 0;
- ChP->TxEnables[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
-
- ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
- ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
- ChP->TxCompare[2] = 0;
- ChP->TxCompare[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
-
- ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
- ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
- ChP->TxReplace1[2] = 0;
- ChP->TxReplace1[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
-
- ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
- ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
- ChP->TxReplace2[2] = 0;
- ChP->TxReplace2[3] = 0;
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
-
- ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
- ChP->TxFIFO = ChOff + _TX_FIFO;
-
- sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
- sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */
- sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
- sOutW(ChP->IndexData,0);
- ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
- ChP->RxFIFO = ChOff + _RX_FIFO;
-
- sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
- sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */
- sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
- sOutW(ChP->IndexData,0);
- sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
- sOutW(ChP->IndexData,0);
- ChP->TxPrioCnt = ChOff + _TXP_CNT;
- sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
- sOutB(ChP->IndexData,0);
- ChP->TxPrioPtr = ChOff + _TXP_PNTR;
- sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
- sOutB(ChP->IndexData,0);
- ChP->TxPrioBuf = ChOff + _TXP_BUF;
- sEnRxProcessor(ChP); /* start the Rx processor */
+int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+ int ChanNum)
+{
+ int i;
+ WordIO_t AiopIO;
+ WordIO_t ChIOOff;
+ Byte_t *ChR;
+ Word_t ChOff;
+ static Byte_t R[4];
+ int brd9600;
+
+ if (ChanNum >= CtlP->AiopNumChan[AiopNum])
+ return (FALSE); /* exceeds num chans in AIOP */
+
+ /* Channel, AIOP, and controller identifiers */
+ ChP->CtlP = CtlP;
+ ChP->ChanID = CtlP->AiopID[AiopNum];
+ ChP->AiopNum = AiopNum;
+ ChP->ChanNum = ChanNum;
+
+ /* Global direct addresses */
+ AiopIO = CtlP->AiopIO[AiopNum];
+ ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
+ ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
+ ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
+ ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
+ ChP->IndexData = AiopIO + _INDX_DATA;
+
+ /* Channel direct addresses */
+ ChIOOff = AiopIO + ChP->ChanNum * 2;
+ ChP->TxRxData = ChIOOff + _TD0;
+ ChP->ChanStat = ChIOOff + _CHN_STAT0;
+ ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
+ ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
+
+ /* Initialize the channel from the RData array */
+ for (i = 0; i < RDATASIZE; i += 4) {
+ R[0] = RData[i];
+ R[1] = RData[i + 1] + 0x10 * ChanNum;
+ R[2] = RData[i + 2];
+ R[3] = RData[i + 3];
+ sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0]));
+ }
+
+ ChR = ChP->R;
+ for (i = 0; i < RREGDATASIZE; i += 4) {
+ ChR[i] = RRegData[i];
+ ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
+ ChR[i + 2] = RRegData[i + 2];
+ ChR[i + 3] = RRegData[i + 3];
+ }
+
+ /* Indexed registers */
+ ChOff = (Word_t) ChanNum *0x1000;
+
+ if (sClockPrescale == 0x14)
+ brd9600 = 47;
+ else
+ brd9600 = 23;
+
+ ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
+ ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
+ ChP->BaudDiv[2] = (Byte_t) brd9600;
+ ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]);
+
+ ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
+ ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
+ ChP->TxControl[2] = 0;
+ ChP->TxControl[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
+
+ ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
+ ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
+ ChP->RxControl[2] = 0;
+ ChP->RxControl[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
+
+ ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
+ ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
+ ChP->TxEnables[2] = 0;
+ ChP->TxEnables[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]);
+
+ ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
+ ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
+ ChP->TxCompare[2] = 0;
+ ChP->TxCompare[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]);
+
+ ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
+ ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
+ ChP->TxReplace1[2] = 0;
+ ChP->TxReplace1[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]);
+
+ ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
+ ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
+ ChP->TxReplace2[2] = 0;
+ ChP->TxReplace2[3] = 0;
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]);
+
+ ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
+ ChP->TxFIFO = ChOff + _TX_FIFO;
+
+ sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
+ sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Tx FIFO count */
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
+ sOutW(ChP->IndexData, 0);
+ ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
+ ChP->RxFIFO = ChOff + _RX_FIFO;
+
+ sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
+ sOutB(ChP->Cmd, (Byte_t) ChanNum); /* remove reset Rx FIFO count */
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
+ sOutW(ChP->IndexData, 0);
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
+ sOutW(ChP->IndexData, 0);
+ ChP->TxPrioCnt = ChOff + _TXP_CNT;
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
+ sOutB(ChP->IndexData, 0);
+ ChP->TxPrioPtr = ChOff + _TXP_PNTR;
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
+ sOutB(ChP->IndexData, 0);
+ ChP->TxPrioBuf = ChOff + _TXP_BUF;
+ sEnRxProcessor(ChP); /* start the Rx processor */
- return(TRUE);
+ return (TRUE);
}
/***************************************************************************
@@ -2626,15 +3336,15 @@
After calling this function a delay of 4 uS is required to ensure
that the receive processor is no longer processing this channel.
*/
-void sStopRxProcessor(CHANNEL_T *ChP)
+void sStopRxProcessor(CHANNEL_T * ChP)
{
- Byte_t R[4];
+ Byte_t R[4];
- R[0] = ChP->R[0];
- R[1] = ChP->R[1];
- R[2] = 0x0a;
- R[3] = ChP->R[3];
- sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
+ R[0] = ChP->R[0];
+ R[1] = ChP->R[1];
+ R[2] = 0x0a;
+ R[3] = ChP->R[3];
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]);
}
/***************************************************************************
@@ -2651,33 +3361,32 @@
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushRxFIFO(CHANNEL_T *ChP)
+void sFlushRxFIFO(CHANNEL_T * ChP)
{
- int i;
- Byte_t Ch; /* channel number within AIOP */
- int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
-
- if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
- return; /* don't need to flush */
-
- RxFIFOEnabled = FALSE;
- if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
- {
- RxFIFOEnabled = TRUE;
- sDisRxFIFO(ChP); /* disable it */
- for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
- sInB(ChP->IntChan); /* depends on bus i/o timing */
- }
- sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
- Ch = (Byte_t)sGetChanNum(ChP);
- sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */
- sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */
- sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
- sOutW(ChP->IndexData,0);
- sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
- sOutW(ChP->IndexData,0);
- if(RxFIFOEnabled)
- sEnRxFIFO(ChP); /* enable Rx FIFO */
+ int i;
+ Byte_t Ch; /* channel number within AIOP */
+ int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
+
+ if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
+ return; /* don't need to flush */
+
+ RxFIFOEnabled = FALSE;
+ if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
+ RxFIFOEnabled = TRUE;
+ sDisRxFIFO(ChP); /* disable it */
+ for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
+ sInB(ChP->IntChan); /* depends on bus i/o timing */
+ }
+ sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */
+ Ch = (Byte_t) sGetChanNum(ChP);
+ sOutB(ChP->Cmd, Ch | RESRXFCNT); /* apply reset Rx FIFO count */
+ sOutB(ChP->Cmd, Ch); /* remove reset Rx FIFO count */
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs); /* clear Rx out ptr */
+ sOutW(ChP->IndexData, 0);
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
+ sOutW(ChP->IndexData, 0);
+ if (RxFIFOEnabled)
+ sEnRxFIFO(ChP); /* enable Rx FIFO */
}
/***************************************************************************
@@ -2694,32 +3403,31 @@
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushTxFIFO(CHANNEL_T *ChP)
+void sFlushTxFIFO(CHANNEL_T * ChP)
{
- int i;
- Byte_t Ch; /* channel number within AIOP */
- int TxEnabled; /* TRUE if transmitter enabled */
-
- if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
- return; /* don't need to flush */
-
- TxEnabled = FALSE;
- if(ChP->TxControl[3] & TX_ENABLE)
- {
- TxEnabled = TRUE;
- sDisTransmit(ChP); /* disable transmitter */
- }
- sStopRxProcessor(ChP); /* stop Rx processor */
- for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */
- sInB(ChP->IntChan); /* depends on bus i/o timing */
- Ch = (Byte_t)sGetChanNum(ChP);
- sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */
- sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */
- sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
- sOutW(ChP->IndexData,0);
- if(TxEnabled)
- sEnTransmit(ChP); /* enable transmitter */
- sStartRxProcessor(ChP); /* restart Rx processor */
+ int i;
+ Byte_t Ch; /* channel number within AIOP */
+ int TxEnabled; /* TRUE if transmitter enabled */
+
+ if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
+ return; /* don't need to flush */
+
+ TxEnabled = FALSE;
+ if (ChP->TxControl[3] & TX_ENABLE) {
+ TxEnabled = TRUE;
+ sDisTransmit(ChP); /* disable transmitter */
+ }
+ sStopRxProcessor(ChP); /* stop Rx processor */
+ for (i = 0; i < 4000 / 200; i++) /* delay 4 uS to allow proc to stop */
+ sInB(ChP->IntChan); /* depends on bus i/o timing */
+ Ch = (Byte_t) sGetChanNum(ChP);
+ sOutB(ChP->Cmd, Ch | RESTXFCNT); /* apply reset Tx FIFO count */
+ sOutB(ChP->Cmd, Ch); /* remove reset Tx FIFO count */
+ sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
+ sOutW(ChP->IndexData, 0);
+ if (TxEnabled)
+ sEnTransmit(ChP); /* enable transmitter */
+ sStartRxProcessor(ChP); /* restart Rx processor */
}
/***************************************************************************
@@ -2735,36 +3443,34 @@
Warnings: No context switches are allowed while executing this function.
*/
-int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
+int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
{
- Byte_t DWBuf[4]; /* buffer for double word writes */
- Word_t *WordPtr; /* must be far because Win SS != DS */
- register DWordIO_t IndexAddr;
-
- if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */
- {
- IndexAddr = ChP->IndexAddr;
- sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
- if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
- return(0); /* nothing sent */
-
- WordPtr = (Word_t *)(&DWBuf[0]);
- *WordPtr = ChP->TxPrioBuf; /* data byte address */
-
- DWBuf[2] = Data; /* data byte value */
- sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
-
- *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
-
- DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
- DWBuf[3] = 0; /* priority buffer pointer */
- sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
- }
- else /* write it to Tx FIFO */
- {
- sWriteTxByte(sGetTxRxDataIO(ChP),Data);
- }
- return(1); /* 1 byte sent */
+ Byte_t DWBuf[4]; /* buffer for double word writes */
+ Word_t *WordPtr; /* must be far because Win SS != DS */
+ register DWordIO_t IndexAddr;
+
+ if (sGetTxCnt(ChP) > 1) { /* write it to Tx priority buffer */
+ IndexAddr = ChP->IndexAddr;
+ sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt); /* get priority buffer status */
+ if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND) /* priority buffer busy */
+ return (0); /* nothing sent */
+
+ WordPtr = (Word_t *) (&DWBuf[0]);
+ *WordPtr = ChP->TxPrioBuf; /* data byte address */
+
+ DWBuf[2] = Data; /* data byte value */
+ sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
+
+ *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */
+
+ DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */
+ DWBuf[3] = 0; /* priority buffer pointer */
+ sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0]))); /* write it out */
+ } else { /* write it to Tx FIFO */
+
+ sWriteTxByte(sGetTxRxDataIO(ChP), Data);
+ }
+ return (1); /* 1 byte sent */
}
/***************************************************************************
@@ -2799,24 +3505,23 @@
enable channel interrupts. This would allow the global interrupt
status register to be used to determine which AIOPs need service.
*/
-void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
+void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
- Byte_t Mask; /* Interrupt Mask Register */
+ Byte_t Mask; /* Interrupt Mask Register */
- ChP->RxControl[2] |=
- ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
+ ChP->RxControl[2] |=
+ ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
- ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
+ ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
- if(Flags & CHANINT_EN)
- {
- Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
- sOutB(ChP->IntMask,Mask);
- }
+ if (Flags & CHANINT_EN) {
+ Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
+ sOutB(ChP->IntMask, Mask);
+ }
}
/***************************************************************************
@@ -2844,19 +3549,98 @@
this channel's bit from being set in the AIOP's Interrupt Channel
Register.
*/
-void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
+void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
- Byte_t Mask; /* Interrupt Mask Register */
+ Byte_t Mask; /* Interrupt Mask Register */
- ChP->RxControl[2] &=
- ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
- ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
- sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
-
- if(Flags & CHANINT_EN)
- {
- Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
- sOutB(ChP->IntMask,Mask);
- }
+ ChP->RxControl[2] &=
+ ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
+ ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
+ sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
+
+ if (Flags & CHANINT_EN) {
+ Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
+ sOutB(ChP->IntMask, Mask);
+ }
+}
+
+void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
+{
+ sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
+}
+
+/*
+ * Not an official SSCI function, but how to reset RocketModems.
+ * ISA bus version
+ */
+void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
+{
+ ByteIO_t addr;
+ Byte_t val;
+
+ addr = CtlP->AiopIO[0] + 0x400;
+ val = sInB(CtlP->MReg3IO);
+ /* if AIOP[1] is not enabled, enable it */
+ if ((val & 2) == 0) {
+ val = sInB(CtlP->MReg2IO);
+ sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
+ sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
+ }
+
+ sEnAiop(CtlP, 1);
+ if (!on)
+ addr += 8;
+ sOutB(addr + chan, 0); /* apply or remove reset */
+ sDisAiop(CtlP, 1);
+}
+
+/*
+ * Not an official SSCI function, but how to reset RocketModems.
+ * PCI bus version
+ */
+void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
+{
+ ByteIO_t addr;
+
+ addr = CtlP->AiopIO[0] + 0x40; /* 2nd AIOP */
+ if (!on)
+ addr += 8;
+ sOutB(addr + chan, 0); /* apply or remove reset */
+}
+
+/* Resets the speaker controller on RocketModem II and III devices */
+static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
+{
+ ByteIO_t addr;
+
+ /* RocketModem II speaker control is at the 8th port location of offset 0x40 */
+ if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
+ addr = CtlP->AiopIO[0] + 0x4F;
+ sOutB(addr, 0);
+ }
+
+ /* RocketModem III speaker control is at the 1st port location of offset 0x80 */
+ if ((model == MODEL_UPCI_RM3_8PORT)
+ || (model == MODEL_UPCI_RM3_4PORT)) {
+ addr = CtlP->AiopIO[0] + 0x88;
+ sOutB(addr, 0);
+ }
+}
+
+/* Returns the line number given the controller (board), aiop and channel number */
+static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
+{
+ return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
+}
+
+/*
+ * Stores the line number associated with a given controller (board), aiop
+ * and channel number.
+ * Returns: The line number assigned
+ */
+static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
+{
+ lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
+ return (nextLineNumber - 1);
}
diff -urN linux-2.5.70-bk10/drivers/char/rocket.h linux-2.5.70-bk11/drivers/char/rocket.h
--- linux-2.5.70-bk10/drivers/char/rocket.h 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk11/drivers/char/rocket.h 2003-06-06 04:38:21.000000000 -0700
@@ -0,0 +1,131 @@
+/*
+ * rocket.h --- the exported interface of the rocket driver to
+ * its configuration program.
+ *
+ * Written by Theodore Ts'o, Copyright 1997.
+ *
+ * Copyright 1994, 1997, 2003 Comtrol Corporation. All Rights Reserved.
+ *
+ * The following source code is subject to Comtrol Corporation's
+ * Developer's License Agreement.
+ *
+ * This source code is protected by United States copyright law and
+ * international copyright treaties.
+ *
+ * This source code may only be used to develop software products that
+ * will operate with Comtrol brand hardware.
+ *
+ * You may not reproduce nor distribute this source code in its original
+ * form but must produce a derivative work which includes portions of
+ * this source code only.
+ *
+ * The portions of this source code which you use in your derivative
+ * work must bear Comtrol's copyright notice:
+ *
+ * Copyright 1994 Comtrol Corporation.
+ *
+ */
+
+/* Model Information Struct */
+typedef struct {
+ unsigned long model;
+ char modelString[80];
+ unsigned long numPorts;
+ int loadrm2;
+ int startingPortNumber;
+} rocketModel_t;
+
+struct rocket_config {
+ int line;
+ int flags;
+ int closing_wait;
+ int close_delay;
+ int port;
+ int reserved[32];
+};
+
+struct rocket_ports {
+ int tty_major;
+ int callout_major;
+ rocketModel_t rocketModel[8];
+};
+
+struct rocket_version {
+ char rocket_version[32];
+ char rocket_date[32];
+ char reserved[64];
+};
+
+/*
+ * Rocketport flags
+ */
+#define ROCKET_CALLOUT_NOHUP 0x00000001
+#define ROCKET_FORCE_CD 0x00000002
+#define ROCKET_HUP_NOTIFY 0x00000004
+#define ROCKET_SPLIT_TERMIOS 0x00000008
+#define ROCKET_SPD_MASK 0x00000070
+#define ROCKET_SPD_HI 0x00000010 /* Use 56000 instead of 38400 bps */
+#define ROCKET_SPD_VHI 0x00000020 /* Use 115200 instead of 38400 bps */
+#define ROCKET_SPD_SHI 0x00000030 /* Use 230400 instead of 38400 bps */
+#define ROCKET_SPD_WARP 0x00000040 /* Use 460800 instead of 38400 bps */
+#define ROCKET_SAK 0x00000080
+#define ROCKET_SESSION_LOCKOUT 0x00000100
+#define ROCKET_PGRP_LOCKOUT 0x00000200
+#define ROCKET_RTS_TOGGLE 0x00000400
+#define ROCKET_MODE_MASK 0x00003000
+#define ROCKET_MODE_RS232 0x00000000
+#define ROCKET_MODE_RS485 0x00001000
+#define ROCKET_MODE_RS422 0x00002000
+#define ROCKET_FLAGS 0x00003FFF
+
+#define ROCKET_USR_MASK 0x0071 /* Legal flags that non-privileged
+ * users can set or reset */
+
+/*
+ * For closing_wait and closing_wait2
+ */
+#define ROCKET_CLOSING_WAIT_NONE 65535
+#define ROCKET_CLOSING_WAIT_INF 0
+
+/*
+ * Rocketport ioctls -- "RP"
+ */
+#define RCKP_GET_STRUCT 0x00525001
+#define RCKP_GET_CONFIG 0x00525002
+#define RCKP_SET_CONFIG 0x00525003
+#define RCKP_GET_PORTS 0x00525004
+#define RCKP_RESET_RM2 0x00525005
+#define RCKP_GET_VERSION 0x00525006
+
+/* Rocketport Models */
+#define MODEL_RP32INTF 0x0001 /* RP 32 port w/external I/F */
+#define MODEL_RP8INTF 0x0002 /* RP 8 port w/external I/F */
+#define MODEL_RP16INTF 0x0003 /* RP 16 port w/external I/F */
+#define MODEL_RP8OCTA 0x0005 /* RP 8 port w/octa cable */
+#define MODEL_RP4QUAD 0x0004 /* RP 4 port w/quad cable */
+#define MODEL_RP8J 0x0006 /* RP 8 port w/RJ11 connectors */
+#define MODEL_RP4J 0x0007 /* RP 4 port w/RJ45 connectors */
+#define MODEL_RP8SNI 0x0008 /* RP 8 port w/ DB78 SNI connector */
+#define MODEL_RP16SNI 0x0009 /* RP 16 port w/ DB78 SNI connector */
+#define MODEL_RPP4 0x000A /* RP Plus 4 port */
+#define MODEL_RPP8 0x000B /* RP Plus 8 port */
+#define MODEL_RP2_232 0x000E /* RP Plus 2 port RS232 */
+#define MODEL_RP2_422 0x000F /* RP Plus 2 port RS232 */
+
+/* Rocketmodem II Models */
+#define MODEL_RP6M 0x000C /* RM 6 port */
+#define MODEL_RP4M 0x000D /* RM 4 port */
+
+/* Universal PCI boards */
+#define MODEL_UPCI_RP32INTF 0x0801 /* RP UPCI 32 port w/external I/F */
+#define MODEL_UPCI_RP8INTF 0x0802 /* RP UPCI 8 port w/external I/F */
+#define MODEL_UPCI_RP16INTF 0x0803 /* RP UPCI 16 port w/external I/F */
+#define MODEL_UPCI_RP8OCTA 0x0805 /* RP UPCI 8 port w/octa cable */
+#define MODEL_UPCI_RM3_8PORT 0x080C /* RP UPCI Rocketmodem III 8 port */
+#define MODEL_UPCI_RM3_4PORT 0x080C /* RP UPCI Rocketmodem III 4 port */
+
+/* Compact PCI 16 port */
+#define MODEL_CPCI_RP16INTF 0x0903 /* RP Compact PCI 16 port w/external I/F */
+
+/* All ISA boards */
+#define MODEL_ISA 0x1000
diff -urN linux-2.5.70-bk10/drivers/char/rocket_int.h linux-2.5.70-bk11/drivers/char/rocket_int.h
--- linux-2.5.70-bk10/drivers/char/rocket_int.h 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/char/rocket_int.h 2003-06-06 04:38:21.000000000 -0700
@@ -3,9 +3,7 @@
*
* Written by Theodore Ts'o, Copyright 1997.
*
- * Portions of this file are....
- *
- * Copyright 1994 Comtrol Corporation. All Rights Reserved.
+ * Copyright 1994, 1997, 2003 Comtrol Corporation. All Rights Reserved.
*
* The following source code is subject to Comtrol Corporation's
* Developer's License Agreement.
@@ -28,23 +26,16 @@
*/
/*
- * Begin Comtrol-provided headers, et. al.
+ * Definition of the types in rcktpt_type
*/
-
-/*
- user definitions for Rocket Toolkit
-
- The following typedefs and defines must be established
- depending on the platform the toolkit is being used
- with.
-
-*/
-
-/************************************************************
-The following sets up the world for use with Linux
-************************************************************/
+#define ROCKET_TYPE_NORMAL 0
+#define ROCKET_TYPE_MODEM 1
+#define ROCKET_TYPE_MODEMII 2
+#define ROCKET_TYPE_MODEMIII 3
+#define ROCKET_TYPE_PC104 4
#include
+#include
typedef unsigned char Byte_t;
typedef unsigned int ByteIO_t;
@@ -55,17 +46,71 @@
typedef unsigned long DWord_t;
typedef unsigned int DWordIO_t;
+/*
+ * Note! Normally the Linux I/O macros already take care of
+ * byte-swapping the I/O instructions. However, all accesses using
+ * sOutDW aren't really 32-bit accesses, but should be handled in byte
+ * order. Hence the use of the cpu_to_le32() macro to byte-swap
+ * things to no-op the byte swapping done by the big-endian outl()
+ * instruction.
+ */
+
+#ifdef ROCKET_DEBUG_IO
+static inline void sOutB(unsigned short port, unsigned char value)
+{
+#ifdef ROCKET_DEBUG_IO
+ printk("sOutB(%x, %x)...", port, value);
+#endif
+ outb_p(value, port);
+}
+
+static inline void sOutW(unsigned short port, unsigned short value)
+{
+#ifdef ROCKET_DEBUG_IO
+ printk("sOutW(%x, %x)...", port, value);
+#endif
+ outw_p(value, port);
+}
+
+static inline void sOutDW(unsigned short port, unsigned long value)
+{
+#ifdef ROCKET_DEBUG_IO
+ printk("sOutDW(%x, %lx)...", port, value);
+#endif
+ outl_p(cpu_to_le32(value), port);
+}
+
+static inline unsigned char sInB(unsigned short port)
+{
+ return inb_p(port);
+}
+
+static inline unsigned short sInW(unsigned short port)
+{
+ return inw_p(port);
+}
+
+#else /* !ROCKET_DEBUG_IO */
#define sOutB(a, b) outb_p(b, a)
#define sOutW(a, b) outw_p(b, a)
-#define sOutDW(a, b) outl_p(b, a)
+#define sOutDW(port, value) outl_p(cpu_to_le32(value), port)
#define sInB(a) (inb_p(a))
#define sInW(a) (inw_p(a))
+#endif /* ROCKET_DEBUG_IO */
-#define sOutStrW(port, addr, count) outsw(port, addr, count)
+/* This is used to move arrays of bytes so byte swapping isn't
+ * appropriate. On Linux 2.3 and above outsw is the same as
+ * outsw_ns, but we use the old form for compatibility with
+ * old kernels. */
+#if defined(__BIG_ENDIAN) && (LINUX_VERSION_CODE < VERSION_CODE(2,3,0))
+#define sOutStrW(port, addr, count) if (count) outsw_ns(port, addr, count)
+#define sInStrW(port, addr, count) if (count) insw_ns(port, addr, count)
+#else
+#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
+#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
+#endif
-#define sInStrW(port, addr, count) insw(port, addr, count)
-
-#define CTL_SIZE 4
+#define CTL_SIZE 8
#define AIOP_CTL_SIZE 4
#define CHAN_AIOP_SIZE 8
#define MAX_PORTS_PER_AIOP 8
@@ -78,219 +123,159 @@
#define isMC 2
/* Controller ID numbers */
-#define CTLID_NULL -1 /* no controller exists */
-#define CTLID_0001 0x0001 /* controller release 1 */
+#define CTLID_NULL -1 /* no controller exists */
+#define CTLID_0001 0x0001 /* controller release 1 */
/* AIOP ID numbers, identifies AIOP type implementing channel */
-#define AIOPID_NULL -1 /* no AIOP or channel exists */
-#define AIOPID_0001 0x0001 /* AIOP release 1 */
+#define AIOPID_NULL -1 /* no AIOP or channel exists */
+#define AIOPID_0001 0x0001 /* AIOP release 1 */
-#define NULLDEV -1 /* identifies non-existant device */
-#define NULLCTL -1 /* identifies non-existant controller */
-#define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */
-#define NULLAIOP -1 /* identifies non-existant AIOP */
-#define NULLCHAN -1 /* identifies non-existant channel */
+#define NULLDEV -1 /* identifies non-existant device */
+#define NULLCTL -1 /* identifies non-existant controller */
+#define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */
+#define NULLAIOP -1 /* identifies non-existant AIOP */
+#define NULLCHAN -1 /* identifies non-existant channel */
/************************************************************************
Global Register Offsets - Direct Access - Fixed values
************************************************************************/
-#define _CMD_REG 0x38 /* Command Register 8 Write */
-#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */
-#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */
-#define _UNUSED 0x3B /* Unused 8 */
-#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */
-#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */
+#define _CMD_REG 0x38 /* Command Register 8 Write */
+#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */
+#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */
+#define _UNUSED 0x3B /* Unused 8 */
+#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */
+#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */
/************************************************************************
Channel Register Offsets for 1st channel in AIOP - Direct Access
************************************************************************/
-#define _TD0 0x00 /* Transmit Data 16 Write */
-#define _RD0 0x00 /* Receive Data 16 Read */
-#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */
-#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */
-#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */
+#define _TD0 0x00 /* Transmit Data 16 Write */
+#define _RD0 0x00 /* Receive Data 16 Read */
+#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */
+#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */
+#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */
/************************************************************************
Tx Control Register Offsets - Indexed - External - Fixed
************************************************************************/
-#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */
-#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */
-#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */
-#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */
-#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */
-#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */
+#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */
+#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */
+#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */
+#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */
+#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */
+#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */
/************************************************************************
Memory Controller Register Offsets - Indexed - External - Fixed
************************************************************************/
-#define _RX_FIFO 0x000 /* Rx FIFO */
-#define _TX_FIFO 0x800 /* Tx FIFO */
-#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */
-#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */
-#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */
-#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */
-#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */
-#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */
-
-#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */
-#define TXFIFO_SIZE 255 /* size of Tx FIFO */
-#define RXFIFO_SIZE 1023 /* size of Rx FIFO */
+#define _RX_FIFO 0x000 /* Rx FIFO */
+#define _TX_FIFO 0x800 /* Tx FIFO */
+#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */
+#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */
+#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */
+#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */
+#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */
+#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */
+
+#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */
+#define TXFIFO_SIZE 255 /* size of Tx FIFO */
+#define RXFIFO_SIZE 1023 /* size of Rx FIFO */
/************************************************************************
Tx Priority Buffer - Indexed - External - Fixed
************************************************************************/
-#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */
-#define TXP_SIZE 0x20 /* 32 bytes */
+#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */
+#define TXP_SIZE 0x20 /* 32 bytes */
/************************************************************************
Channel Register Offsets - Indexed - Internal - Fixed
************************************************************************/
-#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */
-#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */
-#define _BAUD 0xFF4 /* Baud Rate 16 Write */
-#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */
-
-#if 0
-#define CLOCK_PRESC 0x14 /* ?????? new mod 4 (divide by 5) prescale */
-
-#define BRD50 9215
-#define BRD75 6143
-#define BRD110 4188
-#define BRD134 3438
-#define BRD150 3071
-#define BRD200 2303
-#define BRD300 1535
-#define BRD600 767
-#define BRD1200 383
-#define BRD1800 255
-#define BRD2000 229
-#define BRD2400 191
-#define BRD3600 127
-#define BRD4800 95
-#define BRD7200 63
-#define BRD9600 47
-#define BRD14400 31
-#define BRD19200 23
-#define BRD38400 11
-#define BRD57600 7
-#define BRD76800 5
-#define BRD115200 3
-#define BRD230400 1
-#define BRD460800 0
-#endif
-
-#if 0
-
-/* Old clock prescale definition and baud rates associated with it */
-
-#define CLOCK_PRESC 0x19 /* mod 9 (divide by 10) prescale */
-#define BRD50 4607
-#define BRD75 3071
-#define BRD110 2094
-#define BRD134 1712
-#define BRD150 1535
-#define BRD200 1151
-#define BRD300 767
-#define BRD600 383
-#define BRD1200 191
-#define BRD1800 127
-#define BRD2000 114
-#define BRD2400 95
-#define BRD3600 64
-#define BRD4800 47
-#define BRD7200 31
-#define BRD9600 23
-#define BRD14400 15
-#define BRD19200 11
-#define BRD38400 5
-#define BRD57600 3
-#define BRD76800 2
-#define BRD115200 1
-#define BRD230400 0
-
-#endif
-
-#define STMBREAK 0x08 /* BREAK */
-#define STMFRAME 0x04 /* framing error */
-#define STMRCVROVR 0x02 /* receiver over run error */
-#define STMPARITY 0x01 /* parity error */
+#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */
+#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */
+#define _BAUD 0xFF4 /* Baud Rate 16 Write */
+#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */
+
+#define STMBREAK 0x08 /* BREAK */
+#define STMFRAME 0x04 /* framing error */
+#define STMRCVROVR 0x02 /* receiver over run error */
+#define STMPARITY 0x01 /* parity error */
#define STMERROR (STMBREAK | STMFRAME | STMPARITY)
-#define STMBREAKH 0x800 /* BREAK */
-#define STMFRAMEH 0x400 /* framing error */
-#define STMRCVROVRH 0x200 /* receiver over run error */
-#define STMPARITYH 0x100 /* parity error */
+#define STMBREAKH 0x800 /* BREAK */
+#define STMFRAMEH 0x400 /* framing error */
+#define STMRCVROVRH 0x200 /* receiver over run error */
+#define STMPARITYH 0x100 /* parity error */
#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH)
-#define CTS_ACT 0x20 /* CTS input asserted */
-#define DSR_ACT 0x10 /* DSR input asserted */
-#define CD_ACT 0x08 /* CD input asserted */
-#define TXFIFOMT 0x04 /* Tx FIFO is empty */
-#define TXSHRMT 0x02 /* Tx shift register is empty */
-#define RDA 0x01 /* Rx data available */
-#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */
-
-#define STATMODE 0x8000 /* status mode enable bit */
-#define RXFOVERFL 0x2000 /* receive FIFO overflow */
-#define RX2MATCH 0x1000 /* receive compare byte 2 match */
-#define RX1MATCH 0x0800 /* receive compare byte 1 match */
-#define RXBREAK 0x0400 /* received BREAK */
-#define RXFRAME 0x0200 /* received framing error */
-#define RXPARITY 0x0100 /* received parity error */
+#define CTS_ACT 0x20 /* CTS input asserted */
+#define DSR_ACT 0x10 /* DSR input asserted */
+#define CD_ACT 0x08 /* CD input asserted */
+#define TXFIFOMT 0x04 /* Tx FIFO is empty */
+#define TXSHRMT 0x02 /* Tx shift register is empty */
+#define RDA 0x01 /* Rx data available */
+#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */
+
+#define STATMODE 0x8000 /* status mode enable bit */
+#define RXFOVERFL 0x2000 /* receive FIFO overflow */
+#define RX2MATCH 0x1000 /* receive compare byte 2 match */
+#define RX1MATCH 0x0800 /* receive compare byte 1 match */
+#define RXBREAK 0x0400 /* received BREAK */
+#define RXFRAME 0x0200 /* received framing error */
+#define RXPARITY 0x0100 /* received parity error */
#define STATERROR (RXBREAK | RXFRAME | RXPARITY)
-#define CTSFC_EN 0x80 /* CTS flow control enable bit */
-#define RTSTOG_EN 0x40 /* RTS toggle enable bit */
-#define TXINT_EN 0x10 /* transmit interrupt enable */
-#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */
-#define PARITY_EN 0x04 /* enable parity (0 = no parity) */
-#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */
-#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */
-
-#define SETBREAK 0x10 /* send break condition (must clear) */
-#define LOCALLOOP 0x08 /* local loopback set for test */
-#define SET_DTR 0x04 /* assert DTR */
-#define SET_RTS 0x02 /* assert RTS */
-#define TX_ENABLE 0x01 /* enable transmitter */
-
-#define RTSFC_EN 0x40 /* RTS flow control enable */
-#define RXPROC_EN 0x20 /* receive processor enable */
-#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */
-#define TRIG_1 0x08 /* trigger level 1 char */
-#define TRIG_1_2 0x10 /* trigger level 1/2 */
-#define TRIG_7_8 0x18 /* trigger level 7/8 */
-#define TRIG_MASK 0x18 /* trigger level mask */
-#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */
-#define RXINT_EN 0x02 /* Rx interrupt enable */
-#define MCINT_EN 0x01 /* modem change interrupt enable */
-
-#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */
-#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */
-#define SRC_INT 0x08 /* special receive condition interrupt */
-#define DELTA_CD 0x04 /* CD change interrupt */
-#define DELTA_CTS 0x02 /* CTS change interrupt */
-#define DELTA_DSR 0x01 /* DSR change interrupt */
-
-#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */
-#define IGN2_EN 0x08 /* ignore byte 2 enable */
-#define IGN1_EN 0x04 /* ignore byte 1 enable */
-#define COMP2_EN 0x02 /* compare byte 2 enable */
-#define COMP1_EN 0x01 /* compare byte 1 enable */
-
-#define RESET_ALL 0x80 /* reset AIOP (all channels) */
-#define TXOVERIDE 0x40 /* Transmit software off override */
-#define RESETUART 0x20 /* reset channel's UART */
-#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */
-#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */
-
-#define INTSTAT0 0x01 /* AIOP 0 interrupt status */
-#define INTSTAT1 0x02 /* AIOP 1 interrupt status */
-#define INTSTAT2 0x04 /* AIOP 2 interrupt status */
-#define INTSTAT3 0x08 /* AIOP 3 interrupt status */
+#define CTSFC_EN 0x80 /* CTS flow control enable bit */
+#define RTSTOG_EN 0x40 /* RTS toggle enable bit */
+#define TXINT_EN 0x10 /* transmit interrupt enable */
+#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */
+#define PARITY_EN 0x04 /* enable parity (0 = no parity) */
+#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */
+#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */
+
+#define SETBREAK 0x10 /* send break condition (must clear) */
+#define LOCALLOOP 0x08 /* local loopback set for test */
+#define SET_DTR 0x04 /* assert DTR */
+#define SET_RTS 0x02 /* assert RTS */
+#define TX_ENABLE 0x01 /* enable transmitter */
+
+#define RTSFC_EN 0x40 /* RTS flow control enable */
+#define RXPROC_EN 0x20 /* receive processor enable */
+#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */
+#define TRIG_1 0x08 /* trigger level 1 char */
+#define TRIG_1_2 0x10 /* trigger level 1/2 */
+#define TRIG_7_8 0x18 /* trigger level 7/8 */
+#define TRIG_MASK 0x18 /* trigger level mask */
+#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */
+#define RXINT_EN 0x02 /* Rx interrupt enable */
+#define MCINT_EN 0x01 /* modem change interrupt enable */
+
+#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */
+#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */
+#define SRC_INT 0x08 /* special receive condition interrupt */
+#define DELTA_CD 0x04 /* CD change interrupt */
+#define DELTA_CTS 0x02 /* CTS change interrupt */
+#define DELTA_DSR 0x01 /* DSR change interrupt */
+
+#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */
+#define IGN2_EN 0x08 /* ignore byte 2 enable */
+#define IGN1_EN 0x04 /* ignore byte 1 enable */
+#define COMP2_EN 0x02 /* compare byte 2 enable */
+#define COMP1_EN 0x01 /* compare byte 1 enable */
+
+#define RESET_ALL 0x80 /* reset AIOP (all channels) */
+#define TXOVERIDE 0x40 /* Transmit software off override */
+#define RESETUART 0x20 /* reset channel's UART */
+#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */
+#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */
+
+#define INTSTAT0 0x01 /* AIOP 0 interrupt status */
+#define INTSTAT1 0x02 /* AIOP 1 interrupt status */
+#define INTSTAT2 0x04 /* AIOP 2 interrupt status */
+#define INTSTAT3 0x08 /* AIOP 3 interrupt status */
-#define INTR_EN 0x08 /* allow interrupts to host */
-#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */
+#define INTR_EN 0x08 /* allow interrupts to host */
+#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */
/**************************************************************************
MUDBAC remapped for PCI
@@ -299,14 +284,22 @@
#define _CFG_INT_PCI 0x40
#define _PCI_INT_FUNC 0x3A
-#define PCI_STROB 0x2000 /* bit 13 of int aiop register */
-#define INTR_EN_PCI 0x0010 /* allow interrupts to host */
-
+#define PCI_STROB 0x2000 /* bit 13 of int aiop register */
+#define INTR_EN_PCI 0x0010 /* allow interrupts to host */
-#define CHAN3_EN 0x08 /* enable AIOP 3 */
-#define CHAN2_EN 0x04 /* enable AIOP 2 */
-#define CHAN1_EN 0x02 /* enable AIOP 1 */
-#define CHAN0_EN 0x01 /* enable AIOP 0 */
+/*
+ * Definitions for Universal PCI board registers
+ */
+#define _PCI_9030_INT_CTRL 0x4c /* Offsets from BAR1 */
+#define _PCI_9030_GPIO_CTRL 0x54
+#define PCI_INT_CTRL_AIOP 0x0001
+#define PCI_GPIO_CTRL_8PORT 0x4000
+#define _PCI_9030_RING_IND 0xc0 /* Offsets from BAR1 */
+
+#define CHAN3_EN 0x08 /* enable AIOP 3 */
+#define CHAN2_EN 0x04 /* enable AIOP 2 */
+#define CHAN1_EN 0x02 /* enable AIOP 1 */
+#define CHAN0_EN 0x01 /* enable AIOP 0 */
#define FREQ_DIS 0x00
#define FREQ_274HZ 0x60
#define FREQ_137HZ 0x50
@@ -314,75 +307,110 @@
#define FREQ_34HZ 0x30
#define FREQ_17HZ 0x20
#define FREQ_9HZ 0x10
-#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */
+#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */
-#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */
+#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */
#define RDATASIZE 72
#define RREGDATASIZE 52
+/*
+ * AIOP interrupt bits for ISA/PCI boards and UPCI boards.
+ */
+#define AIOP_INTR_BIT_0 0x0001
+#define AIOP_INTR_BIT_1 0x0002
+#define AIOP_INTR_BIT_2 0x0004
+#define AIOP_INTR_BIT_3 0x0008
+
+#define AIOP_INTR_BITS ( \
+ AIOP_INTR_BIT_0 \
+ | AIOP_INTR_BIT_1 \
+ | AIOP_INTR_BIT_2 \
+ | AIOP_INTR_BIT_3)
+
+#define UPCI_AIOP_INTR_BIT_0 0x0004
+#define UPCI_AIOP_INTR_BIT_1 0x0020
+#define UPCI_AIOP_INTR_BIT_2 0x0100
+#define UPCI_AIOP_INTR_BIT_3 0x0800
+
+#define UPCI_AIOP_INTR_BITS ( \
+ UPCI_AIOP_INTR_BIT_0 \
+ | UPCI_AIOP_INTR_BIT_1 \
+ | UPCI_AIOP_INTR_BIT_2 \
+ | UPCI_AIOP_INTR_BIT_3)
+
/* Controller level information structure */
-typedef struct
-{
- int CtlID;
- int CtlNum;
- int BusType;
- WordIO_t PCIIO;
- ByteIO_t MBaseIO;
- ByteIO_t MReg1IO;
- ByteIO_t MReg2IO;
- ByteIO_t MReg3IO;
- Byte_t MReg2;
- Byte_t MReg3;
- int NumAiop;
- WordIO_t AiopIO[AIOP_CTL_SIZE];
- ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
- int AiopID[AIOP_CTL_SIZE];
- int AiopNumChan[AIOP_CTL_SIZE];
+typedef struct {
+ int CtlID;
+ int CtlNum;
+ int BusType;
+ int boardType;
+ int isUPCI;
+ WordIO_t PCIIO;
+ WordIO_t PCIIO2;
+ ByteIO_t MBaseIO;
+ ByteIO_t MReg1IO;
+ ByteIO_t MReg2IO;
+ ByteIO_t MReg3IO;
+ Byte_t MReg2;
+ Byte_t MReg3;
+ int NumAiop;
+ int AltChanRingIndicator;
+ ByteIO_t UPCIRingInd;
+ WordIO_t AiopIO[AIOP_CTL_SIZE];
+ ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
+ int AiopID[AIOP_CTL_SIZE];
+ int AiopNumChan[AIOP_CTL_SIZE];
+ Word_t *AiopIntrBits;
} CONTROLLER_T;
typedef CONTROLLER_T CONTROLLER_t;
/* Channel level information structure */
-typedef struct
-{
- CONTROLLER_T *CtlP;
- int AiopNum;
- int ChanID;
- int ChanNum;
-
- ByteIO_t Cmd;
- ByteIO_t IntChan;
- ByteIO_t IntMask;
- DWordIO_t IndexAddr;
- WordIO_t IndexData;
-
- WordIO_t TxRxData;
- WordIO_t ChanStat;
- WordIO_t TxRxCount;
- ByteIO_t IntID;
-
- Word_t TxFIFO;
- Word_t TxFIFOPtrs;
- Word_t RxFIFO;
- Word_t RxFIFOPtrs;
- Word_t TxPrioCnt;
- Word_t TxPrioPtr;
- Word_t TxPrioBuf;
-
- Byte_t R[RREGDATASIZE];
-
- Byte_t BaudDiv[4];
- Byte_t TxControl[4];
- Byte_t RxControl[4];
- Byte_t TxEnables[4];
- Byte_t TxCompare[4];
- Byte_t TxReplace1[4];
- Byte_t TxReplace2[4];
+typedef struct {
+ CONTROLLER_T *CtlP;
+ int AiopNum;
+ int ChanID;
+ int ChanNum;
+ int rtsToggle;
+
+ ByteIO_t Cmd;
+ ByteIO_t IntChan;
+ ByteIO_t IntMask;
+ DWordIO_t IndexAddr;
+ WordIO_t IndexData;
+
+ WordIO_t TxRxData;
+ WordIO_t ChanStat;
+ WordIO_t TxRxCount;
+ ByteIO_t IntID;
+
+ Word_t TxFIFO;
+ Word_t TxFIFOPtrs;
+ Word_t RxFIFO;
+ Word_t RxFIFOPtrs;
+ Word_t TxPrioCnt;
+ Word_t TxPrioPtr;
+ Word_t TxPrioBuf;
+
+ Byte_t R[RREGDATASIZE];
+
+ Byte_t BaudDiv[4];
+ Byte_t TxControl[4];
+ Byte_t RxControl[4];
+ Byte_t TxEnables[4];
+ Byte_t TxCompare[4];
+ Byte_t TxReplace1[4];
+ Byte_t TxReplace2[4];
} CHANNEL_T;
typedef CHANNEL_T CHANNEL_t;
-typedef CHANNEL_T * CHANPTR_T;
+typedef CHANNEL_T *CHANPTR_T;
+
+#define InterfaceModeRS232 0x00
+#define InterfaceModeRS422 0x08
+#define InterfaceModeRS485 0x10
+#define InterfaceModeRS232T 0x18
/***************************************************************************
Function: sClrBreak
@@ -391,10 +419,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sClrBreak(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] &= ~SETBREAK; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sClrDTR
@@ -403,10 +431,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sClrDTR(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] &= ~SET_DTR; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sClrRTS
@@ -415,10 +443,11 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sClrRTS(ChP) \
-{ \
+do { \
+ if ((ChP)->rtsToggle) break; \
(ChP)->TxControl[3] &= ~SET_RTS; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sClrTxXOFF
@@ -427,10 +456,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sClrTxXOFF(ChP) \
-{ \
+do { \
sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \
sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \
-}
+} while (0)
/***************************************************************************
Function: sCtlNumToCtlPtr
@@ -452,10 +481,22 @@
/***************************************************************************
Function: sPCIControllerEOI
Purpose: Strobe the PCI End Of Interrupt bit.
+ For the UPCI boards, toggle the AIOP interrupt enable bit
+ (this was taken from the Windows driver).
Call: sPCIControllerEOI(CtlP)
CONTROLLER_T *CtlP; Ptr to controller structure
*/
-#define sPCIControllerEOI(CTLP) sOutW((CTLP)->PCIIO, PCI_STROB)
+#define sPCIControllerEOI(CTLP) \
+do { \
+ if ((CTLP)->isUPCI) { \
+ Word_t w = sInW((CTLP)->PCIIO); \
+ sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \
+ sOutW((CTLP)->PCIIO, w); \
+ } \
+ else { \
+ sOutW((CTLP)->PCIIO, PCI_STROB); \
+ } \
+} while (0)
/***************************************************************************
Function: sDisAiop
@@ -465,10 +506,10 @@
int AiopNum; Number of AIOP on controller
*/
#define sDisAiop(CTLP,AIOPNUM) \
-{ \
+do { \
(CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \
sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-}
+} while (0)
/***************************************************************************
Function: sDisCTSFlowCtl
@@ -477,10 +518,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sDisCTSFlowCtl(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] &= ~CTSFC_EN; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sDisIXANY
@@ -489,10 +530,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sDisIXANY(ChP) \
-{ \
+do { \
(ChP)->R[0x0e] = 0x86; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \
-}
+} while (0)
/***************************************************************************
Function: DisParity
@@ -503,10 +544,23 @@
sDisParity(), sSetOddParity(), and sSetEvenParity().
*/
#define sDisParity(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] &= ~PARITY_EN; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
+
+/***************************************************************************
+Function: sDisRTSToggle
+Purpose: Disable RTS toggle
+Call: sDisRTSToggle(ChP)
+ CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisRTSToggle(ChP) \
+do { \
+ (ChP)->TxControl[2] &= ~RTSTOG_EN; \
+ sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
+ (ChP)->rtsToggle = 0; \
+} while (0)
/***************************************************************************
Function: sDisRxFIFO
@@ -515,10 +569,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sDisRxFIFO(ChP) \
-{ \
+do { \
(ChP)->R[0x32] = 0x0a; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \
-}
+} while (0)
/***************************************************************************
Function: sDisRxStatusMode
@@ -542,10 +596,10 @@
and transmit shift register going completely empty.
*/
#define sDisTransmit(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] &= ~TX_ENABLE; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sDisTxSoftFlowCtl
@@ -554,10 +608,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sDisTxSoftFlowCtl(ChP) \
-{ \
+do { \
(ChP)->R[0x06] = 0x8a; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \
-}
+} while (0)
/***************************************************************************
Function: sEnAiop
@@ -567,10 +621,10 @@
int AiopNum; Number of AIOP on controller
*/
#define sEnAiop(CTLP,AIOPNUM) \
-{ \
+do { \
(CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \
sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-}
+} while (0)
/***************************************************************************
Function: sEnCTSFlowCtl
@@ -579,10 +633,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sEnCTSFlowCtl(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] |= CTSFC_EN; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sEnIXANY
@@ -591,10 +645,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sEnIXANY(ChP) \
-{ \
+do { \
(ChP)->R[0x0e] = 0x21; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x0c]); \
-}
+} while (0)
/***************************************************************************
Function: EnParity
@@ -608,10 +662,28 @@
functions sSetOddParity() or sSetEvenParity().
*/
#define sEnParity(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] |= PARITY_EN; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
+
+/***************************************************************************
+Function: sEnRTSToggle
+Purpose: Enable RTS toggle
+Call: sEnRTSToggle(ChP)
+ CHANNEL_T *ChP; Ptr to channel structure
+Comments: This function will disable RTS flow control and clear the RTS
+ line to allow operation of RTS toggle.
+*/
+#define sEnRTSToggle(ChP) \
+do { \
+ (ChP)->RxControl[2] &= ~RTSFC_EN; \
+ sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \
+ (ChP)->TxControl[2] |= RTSTOG_EN; \
+ (ChP)->TxControl[3] &= ~SET_RTS; \
+ sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
+ (ChP)->rtsToggle = 1; \
+} while (0)
/***************************************************************************
Function: sEnRxFIFO
@@ -620,10 +692,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sEnRxFIFO(ChP) \
-{ \
+do { \
(ChP)->R[0x32] = 0x08; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \
-}
+} while (0)
/***************************************************************************
Function: sEnRxProcessor
@@ -641,10 +713,10 @@
microcode has been downloaded.
*/
#define sEnRxProcessor(ChP) \
-{ \
+do { \
(ChP)->RxControl[2] |= RXPROC_EN; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sEnRxStatusMode
@@ -665,10 +737,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sEnTransmit(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] |= TX_ENABLE; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sEnTxSoftFlowCtl
@@ -677,10 +749,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sEnTxSoftFlowCtl(ChP) \
-{ \
+do { \
(ChP)->R[0x06] = 0xc5; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \
-}
+} while (0)
/***************************************************************************
Function: sGetAiopIntStatus
@@ -774,6 +846,18 @@
*/
#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat)
+/**********************************************************************
+ * Get RI status of channel
+ * Defined as a function in rocket.c -aes
+ */
+#if 0
+#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \
+ (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \
+ (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \
+ (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \
+ 0))
+#endif
+
/***************************************************************************
Function: sGetControllerIntStatus
Purpose: Get the controller interrupt status
@@ -798,7 +882,10 @@
was generated from periodic. If a bit is set the
AIOP is interrupting.
*/
-#define sPCIGetControllerIntStatus(CTLP) ((sInW((CTLP)->PCIIO) >> 8) & 0x1f)
+#define sPCIGetControllerIntStatus(CTLP) \
+ ((CTLP)->isUPCI ? \
+ (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \
+ ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS))
/***************************************************************************
@@ -834,7 +921,7 @@
/***************************************************************************
Function: sInitChanDefaults
-Purpose: Initialize a channel structure to its default state.
+Purpose: Initialize a channel structure to it's default state.
Call: sInitChanDefaults(ChP)
CHANNEL_T *ChP; Ptr to the channel structure
Comments: This function must be called once for every channel structure
@@ -842,12 +929,12 @@
*/
#define sInitChanDefaults(ChP) \
-{ \
+do { \
(ChP)->CtlP = NULLCTLPTR; \
(ChP)->AiopNum = NULLAIOP; \
(ChP)->ChanID = AIOPID_NULL; \
(ChP)->ChanNum = NULLCHAN; \
-}
+} while (0)
/***************************************************************************
Function: sResetAiopByNum
@@ -857,10 +944,10 @@
AIOPNUM; AIOP index
*/
#define sResetAiopByNum(CTLP,AIOPNUM) \
-{ \
+do { \
sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \
sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \
-}
+} while (0)
/***************************************************************************
Function: sSendBreak
@@ -869,10 +956,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSendBreak(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] |= SETBREAK; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetBaud
@@ -882,11 +969,11 @@
Word_t Divisor; 16 bit baud rate divisor for channel
*/
#define sSetBaud(ChP,DIVISOR) \
-{ \
+do { \
(ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \
(ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->BaudDiv[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetData7
@@ -895,10 +982,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetData7(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] &= ~DATA8BIT; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetData8
@@ -907,10 +994,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetData8(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] |= DATA8BIT; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetDTR
@@ -919,10 +1006,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetDTR(ChP) \
-{ \
+do { \
(ChP)->TxControl[3] |= SET_DTR; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetEvenParity
@@ -936,10 +1023,10 @@
sEnParity().
*/
#define sSetEvenParity(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] |= EVEN_PAR; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetOddParity
@@ -953,10 +1040,10 @@
sEnParity().
*/
#define sSetOddParity(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] &= ~EVEN_PAR; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetRTS
@@ -965,10 +1052,11 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetRTS(ChP) \
-{ \
+do { \
+ if ((ChP)->rtsToggle) break; \
(ChP)->TxControl[3] |= SET_RTS; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetRxTrigger
@@ -990,11 +1078,11 @@
*/
#define sSetRxTrigger(ChP,LEVEL) \
-{ \
+do { \
(ChP)->RxControl[2] &= ~TRIG_MASK; \
(ChP)->RxControl[2] |= LEVEL; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetStop1
@@ -1003,10 +1091,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetStop1(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] &= ~STOP2; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetStop2
@@ -1015,10 +1103,10 @@
CHANNEL_T *ChP; Ptr to channel structure
*/
#define sSetStop2(ChP) \
-{ \
+do { \
(ChP)->TxControl[2] |= STOP2; \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \
-}
+} while (0)
/***************************************************************************
Function: sSetTxXOFFChar
@@ -1028,10 +1116,10 @@
Byte_t Ch; The value to set the Tx XOFF character to
*/
#define sSetTxXOFFChar(ChP,CH) \
-{ \
+do { \
(ChP)->R[0x07] = (CH); \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \
-}
+} while (0)
/***************************************************************************
Function: sSetTxXONChar
@@ -1041,10 +1129,10 @@
Byte_t Ch; The value to set the Tx XON character to
*/
#define sSetTxXONChar(ChP,CH) \
-{ \
+do { \
(ChP)->R[0x0b] = (CH); \
sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x08]); \
-}
+} while (0)
/***************************************************************************
Function: sStartRxProcessor
@@ -1069,37 +1157,38 @@
*/
#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-int sInitController( CONTROLLER_T *CtlP,
- int CtlNum,
- ByteIO_t MudbacIO,
- ByteIO_t *AiopIOList,
- int AiopIOListSize,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly);
-
-int sPCIInitController( CONTROLLER_T *CtlP,
- int CtlNum,
- ByteIO_t *AiopIOList,
- int AiopIOListSize,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly);
+int sInitController(CONTROLLER_T * CtlP,
+ int CtlNum,
+ ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList,
+ int AiopIOListSize,
+ int IRQNum, Byte_t Frequency, int PeriodicOnly);
+
+int sPCIInitController(CONTROLLER_T * CtlP,
+ int CtlNum,
+ ByteIO_t * AiopIOList,
+ int AiopIOListSize,
+ WordIO_t ConfigIO,
+ int IRQNum,
+ Byte_t Frequency,
+ int PeriodicOnly,
+ int altChanRingIndicator, int UPCIRingInd);
int sReadAiopID(ByteIO_t io);
int sReadAiopNumChan(WordIO_t io);
-int sInitChan( CONTROLLER_T *CtlP,
- CHANNEL_T *ChP,
- int AiopNum,
- int ChanNum);
-Byte_t sGetRxErrStatus(CHANNEL_T *ChP);
-void sStopRxProcessor(CHANNEL_T *ChP);
-void sStopSWInFlowCtl(CHANNEL_T *ChP);
-void sFlushRxFIFO(CHANNEL_T *ChP);
-void sFlushTxFIFO(CHANNEL_T *ChP);
-int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data);
-void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags);
-void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags);
+int sInitChan(CONTROLLER_T * CtlP,
+ CHANNEL_T * ChP, int AiopNum, int ChanNum);
+Byte_t sGetRxErrStatus(CHANNEL_T * ChP);
+void sStopRxProcessor(CHANNEL_T * ChP);
+void sStopSWInFlowCtl(CHANNEL_T * ChP);
+void sFlushRxFIFO(CHANNEL_T * ChP);
+void sFlushTxFIFO(CHANNEL_T * ChP);
+int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
+void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
+void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
+void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
+void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
+void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
extern Byte_t R[RDATASIZE];
extern CONTROLLER_T sController[CTL_SIZE];
@@ -1108,7 +1197,6 @@
extern Byte_t sBitMapSetTbl[8];
extern int sClockPrescale;
-
/*
* Begin Linux specific definitions for the Rocketport driver
*
@@ -1116,34 +1204,45 @@
*/
struct r_port {
- int magic;
- int line;
- int flags;
- int count;
- int blocked_open;
- struct tty_struct *tty;
- int board:2;
- int aiop:2;
- int chan:3;
+ int magic;
+ int line;
+ int flags;
+ int count;
+ int blocked_open;
+ struct tty_struct *tty;
+ unsigned int board:3;
+ unsigned int aiop:2;
+ unsigned int chan:3;
CONTROLLER_t *ctlp;
- CHANNEL_t channel;
- int closing_wait;
- int close_delay;
- int intmask;
- int xmit_fifo_room; /* room in xmit fifo */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- int cd_status;
- int ignore_status_mask;
- int read_status_mask;
- int cps;
- struct termios normal_termios;
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
+ CHANNEL_t channel;
+ int closing_wait;
+ int close_delay;
+ int intmask;
+ int xmit_fifo_room; /* room in xmit fifo */
+ unsigned char *xmit_buf;
+ int xmit_head;
+ int xmit_tail;
+ int xmit_cnt;
+ int session;
+ int pgrp;
+ int cd_status;
+ int ignore_status_mask;
+ int read_status_mask;
+ int cps;
+ struct termios normal_termios;
+ struct termios callout_termios;
+
+#ifdef DECLARE_WAITQUEUE
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+#else
+ struct wait_queue *open_wait;
+ struct wait_queue *close_wait;
+#endif
+ spinlock_t slock;
+ struct semaphore write_sem;
};
-
+
#define RPORT_MAGIC 0x525001
#define NUM_BOARDS 8
@@ -1158,16 +1257,14 @@
#define WAKEUP_CHARS 256
/* Internal flags used only by the rocketport driver */
-#define ROCKET_INITIALIZED 0x80000000 /* Port is active */
-#define ROCKET_CLOSING 0x40000000 /* Serial port is closing */
-#define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */
-#define ROCKET_CALLOUT_ACTIVE 0x10000000 /* Callout port is active */
+#define ROCKET_INITIALIZED 0x80000000 /* Port is active */
+#define ROCKET_CLOSING 0x40000000 /* Serial port is closing */
+#define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */
+#define ROCKET_CALLOUT_ACTIVE 0x10000000 /* Callout port is active */
-/*
- * tty subtypes
- *
- */
+/* tty subtypes */
#define SERIAL_TYPE_NORMAL 1
+#define SERIAL_TYPE_CALLOUT 2
/*
* Assigned major numbers for the Comtrol Rocketport
@@ -1175,9 +1272,6 @@
#define TTY_ROCKET_MAJOR 46
#define CUA_ROCKET_MAJOR 47
-/*
- * Utility function.
- */
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -1188,27 +1282,65 @@
#undef PCI_DEVICE_ID_RP8INTF
#undef PCI_DEVICE_ID_RP16INTF
#undef PCI_DEVICE_ID_RP32INTF
+#undef PCI_DEVICE_ID_URP8OCTA
+#undef PCI_DEVICE_ID_URP8INTF
+#undef PCI_DEVICE_ID_URP16INTF
+#undef PCI_DEVICE_ID_CRP16INTF
+#undef PCI_DEVICE_ID_URP32INTF
#endif
+/* Comtrol PCI Vendor ID */
#define PCI_VENDOR_ID_RP 0x11fe
-#define PCI_DEVICE_ID_RP32INTF 0x0001
-#define PCI_DEVICE_ID_RP8INTF 0x0002
-#define PCI_DEVICE_ID_RP16INTF 0x0003
-#define PCI_DEVICE_ID_RP8OCTA 0x0005
-#ifndef PCI_DEVICE_ID_RP4QUAD
-#define PCI_DEVICE_ID_RP4QUAD 0x0004
-#endif
-#ifndef PCI_DEVICE_ID_RP8J
-#define PCI_DEVICE_ID_RP8J 0x0006
-#endif
-#ifndef PCI_DEVICE_ID_RPP4
-#define PCI_DEVICE_ID_RPP4 0x000A
-#endif
-#ifndef PCI_DEVICE_ID_RPP8
-#define PCI_DEVICE_ID_RPP8 0x000B
-#endif
-#ifndef PCI_DEVICE_ID_RP8M
-#define PCI_DEVICE_ID_RP8M 0x000C
-#endif
+/* Comtrol Device ID's */
+#define PCI_DEVICE_ID_RP32INTF 0x0001 /* Rocketport 32 port w/external I/F */
+#define PCI_DEVICE_ID_RP8INTF 0x0002 /* Rocketport 8 port w/external I/F */
+#define PCI_DEVICE_ID_RP16INTF 0x0003 /* Rocketport 16 port w/external I/F */
+#define PCI_DEVICE_ID_RP4QUAD 0x0004 /* Rocketport 4 port w/quad cable */
+#define PCI_DEVICE_ID_RP8OCTA 0x0005 /* Rocketport 8 port w/octa cable */
+#define PCI_DEVICE_ID_RP8J 0x0006 /* Rocketport 8 port w/RJ11 connectors */
+#define PCI_DEVICE_ID_RP4J 0x0007 /* Rocketport 4 port w/RJ11 connectors */
+#define PCI_DEVICE_ID_RP8SNI 0x0008 /* Rocketport 8 port w/ DB78 SNI (Siemens) connector */
+#define PCI_DEVICE_ID_RP16SNI 0x0009 /* Rocketport 16 port w/ DB78 SNI (Siemens) connector */
+#define PCI_DEVICE_ID_RPP4 0x000A /* Rocketport Plus 4 port */
+#define PCI_DEVICE_ID_RPP8 0x000B /* Rocketport Plus 8 port */
+#define PCI_DEVICE_ID_RP6M 0x000C /* RocketModem 6 port */
+#define PCI_DEVICE_ID_RP4M 0x000D /* RocketModem 4 port */
+#define PCI_DEVICE_ID_RP2_232 0x000E /* Rocketport Plus 2 port RS232 */
+#define PCI_DEVICE_ID_RP2_422 0x000F /* Rocketport Plus 2 port RS422 */
+
+/* Universal PCI boards */
+#define PCI_DEVICE_ID_URP32INTF 0x0801 /* Rocketport UPCI 32 port w/external I/F */
+#define PCI_DEVICE_ID_URP8INTF 0x0802 /* Rocketport UPCI 8 port w/external I/F */
+#define PCI_DEVICE_ID_URP16INTF 0x0803 /* Rocketport UPCI 16 port w/external I/F */
+#define PCI_DEVICE_ID_URP8OCTA 0x0805 /* Rocketport UPCI 8 port w/octa cable */
+#define PCI_DEVICE_ID_UPCI_RM3_8PORT 0x080C /* Rocketmodem III 8 port */
+#define PCI_DEVICE_ID_UPCI_RM3_4PORT 0x080D /* Rocketmodem III 4 port */
+
+/* Compact PCI device */
+#define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */
+
+/* Taking care of some kernel incompatibilities... */
+#if LINUX_VERSION_CODE > VERSION_CODE(2,5,68)
+
+#define TTY_GET_LINE(t) t->index
+
+#define TTY_DRIVER_MINOR_START(t) t->driver->minor_start
+#define TTY_DRIVER_SUBTYPE(t) t->driver->subtype
+#define TTY_DRIVER_NAME(t) t->driver->name
+#define TTY_DRIVER_NAME_BASE(t) t->driver->name_base
+#define TTY_DRIVER_FLUSH_BUFFER_EXISTS(t) t->driver->flush_buffer
+#define TTY_DRIVER_FLUSH_BUFFER(t) t->driver->flush_buffer(t)
+
+#else
+
+#define TTY_GET_LINE(t) minor(t->device) - TTY_DRIVER_MINOR_START(t)
+
+#define TTY_DRIVER_MINOR_START(t) t->driver.minor_start
+#define TTY_DRIVER_SUBTYPE(t) t->driver.subtype
+#define TTY_DRIVER_NAME(t) t->driver.name
+#define TTY_DRIVER_NAME_BASE(t) t->driver.name_base
+#define TTY_DRIVER_FLUSH_BUFFER_EXISTS(t) t->driver.flush_buffer
+#define TTY_DRIVER_FLUSH_BUFFER(t) t->driver.flush_buffer(t)
+#endif
diff -urN linux-2.5.70-bk10/drivers/char/tty_io.c linux-2.5.70-bk11/drivers/char/tty_io.c
--- linux-2.5.70-bk10/drivers/char/tty_io.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/char/tty_io.c 2003-06-06 04:38:22.000000000 -0700
@@ -2093,10 +2093,6 @@
# define tty_unregister_devfs(driver, index) do { } while (0)
#endif /* CONFIG_DEVFS_FS */
-static struct class tty_class = {
- .name = "tty",
-};
-
struct tty_dev {
struct list_head node;
dev_t dev;
@@ -2104,6 +2100,17 @@
};
#define to_tty_dev(d) container_of(d, struct tty_dev, class_dev)
+static void release_tty_dev(struct class_device *class_dev)
+{
+ struct tty_dev *tty_dev = to_tty_dev(class_dev);
+ kfree(tty_dev);
+}
+
+static struct class tty_class = {
+ .name = "tty",
+ .release = &release_tty_dev,
+};
+
static LIST_HEAD(tty_dev_list);
static spinlock_t tty_dev_list_lock = SPIN_LOCK_UNLOCKED;
@@ -2167,7 +2174,6 @@
list_del(&tty_dev->node);
spin_unlock(&tty_dev_list_lock);
class_device_unregister(&tty_dev->class_dev);
- kfree(tty_dev);
} else {
spin_unlock(&tty_dev_list_lock);
}
diff -urN linux-2.5.70-bk10/drivers/i2c/Kconfig linux-2.5.70-bk11/drivers/i2c/Kconfig
--- linux-2.5.70-bk10/drivers/i2c/Kconfig 2003-05-26 18:00:25.000000000 -0700
+++ linux-2.5.70-bk11/drivers/i2c/Kconfig 2003-06-06 04:38:22.000000000 -0700
@@ -144,7 +144,7 @@
config I2C_KEYWEST
tristate "Powermac Keywest I2C interface"
- depends on I2C && ALL_PPC
+ depends on I2C && PPC_PMAC
help
This supports the use of the I2C interface in the combo-I/O
chip on recent Apple machines. Say Y if you have such a machine.
diff -urN linux-2.5.70-bk10/drivers/i2c/chips/w83781d.c linux-2.5.70-bk11/drivers/i2c/chips/w83781d.c
--- linux-2.5.70-bk10/drivers/i2c/chips/w83781d.c 2003-05-26 18:00:19.000000000 -0700
+++ linux-2.5.70-bk11/drivers/i2c/chips/w83781d.c 2003-06-06 04:38:22.000000000 -0700
@@ -1031,27 +1031,129 @@
return i2c_detect(adapter, &addr_data, w83781d_detect);
}
+/* Assumes that adapter is of I2C, not ISA variety.
+ * OTHERWISE DON'T CALL THIS
+ */
+static int
+w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
+ struct i2c_client *new_client)
+{
+ int i, val1 = 0, id;
+ int err;
+ const char *client_name;
+ struct w83781d_data *data = i2c_get_clientdata(new_client);
+
+ if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto ERROR_SC_0;
+ }
+ memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
+
+ id = i2c_adapter_id(adapter);
+
+ if (force_subclients[0] == id && force_subclients[1] == address) {
+ for (i = 2; i <= 3; i++) {
+ if (force_subclients[i] < 0x48 ||
+ force_subclients[i] > 0x4f) {
+ dev_err(&new_client->dev, "Invalid subclient "
+ "address %d; must be 0x48-0x4f\n",
+ force_subclients[i]);
+ err = -EINVAL;
+ goto ERROR_SC_1;
+ }
+ }
+ w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR,
+ (force_subclients[2] & 0x07) |
+ ((force_subclients[3] & 0x07) << 4));
+ data->lm75[0].addr = force_subclients[2];
+ } else {
+ val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR);
+ data->lm75[0].addr = 0x48 + (val1 & 0x07);
+ }
+
+ if (kind != w83783s) {
+ if (force_subclients[0] == id &&
+ force_subclients[1] == address) {
+ data->lm75[1].addr = force_subclients[3];
+ } else {
+ data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
+ }
+ if (data->lm75[0].addr == data->lm75[1].addr) {
+ dev_err(&new_client->dev,
+ "Duplicate addresses 0x%x for subclients.\n",
+ data->lm75[0].addr);
+ err = -EBUSY;
+ goto ERROR_SC_1;
+ }
+ }
+
+ if (kind == w83781d)
+ client_name = "W83781D subclient";
+ else if (kind == w83782d)
+ client_name = "W83782D subclient";
+ else if (kind == w83783s)
+ client_name = "W83783S subclient";
+ else if (kind == w83627hf)
+ client_name = "W83627HF subclient";
+ else if (kind == as99127f)
+ client_name = "AS99127F subclient";
+ else
+ client_name = "unknown subclient?";
+
+ for (i = 0; i <= 1; i++) {
+ /* store all data in w83781d */
+ i2c_set_clientdata(&data->lm75[i], NULL);
+ data->lm75[i].adapter = adapter;
+ data->lm75[i].driver = &w83781d_driver;
+ data->lm75[i].flags = 0;
+ strlcpy(data->lm75[i].dev.name, client_name,
+ DEVICE_NAME_SIZE);
+ if ((err = i2c_attach_client(&(data->lm75[i])))) {
+ dev_err(&new_client->dev, "Subclient %d "
+ "registration at address 0x%x "
+ "failed.\n", i, data->lm75[i].addr);
+ if (i == 1)
+ goto ERROR_SC_2;
+ goto ERROR_SC_1;
+ }
+ if (kind == w83783s)
+ break;
+ }
+
+ return 0;
+
+/* Undo inits in case of errors */
+ERROR_SC_2:
+ i2c_detach_client(&(data->lm75[0]));
+ERROR_SC_1:
+ kfree(data->lm75);
+ERROR_SC_0:
+ return err;
+}
+
static int
w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
{
- int i = 0, val1 = 0, val2, id;
+ int i = 0, val1 = 0, val2;
struct i2c_client *new_client;
struct w83781d_data *data;
- int err = 0;
- const char *type_name = "";
+ int err;
const char *client_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
enum vendor { winbond, asus } vendid;
if (!is_isa
- && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ err = -EINVAL;
goto ERROR0;
+ }
- if (is_isa) {
- if (!request_region(address, W83781D_EXTENT, "w83781d"))
+ if (is_isa)
+ if (!request_region(address, W83781D_EXTENT, "w83781d")) {
+ err = -EBUSY;
goto ERROR0;
- release_region(address, W83781D_EXTENT);
- }
+ }
/* Probe whether there is anything available on this address. Already
done for SMBus clients */
@@ -1059,15 +1161,21 @@
if (is_isa) {
#define REALLY_SLOW_IO
- /* We need the timeouts for at least some LM78-like chips. But only
- if we read 'undefined' registers. */
+ /* We need the timeouts for at least some LM78-like
+ chips. But only if we read 'undefined' registers. */
i = inb_p(address + 1);
- if (inb_p(address + 2) != i)
- goto ERROR0;
- if (inb_p(address + 3) != i)
- goto ERROR0;
- if (inb_p(address + 7) != i)
- goto ERROR0;
+ if (inb_p(address + 2) != i) {
+ err = -ENODEV;
+ goto ERROR1;
+ }
+ if (inb_p(address + 3) != i) {
+ err = -ENODEV;
+ goto ERROR1;
+ }
+ if (inb_p(address + 7) != i) {
+ err = -ENODEV;
+ goto ERROR1;
+ }
#undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */
@@ -1075,7 +1183,8 @@
outb_p(~i & 0x7f, address + 5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
outb_p(i, address + 5);
- return 0;
+ err = -ENODEV;
+ goto ERROR1;
}
}
}
@@ -1087,7 +1196,7 @@
if (!(new_client = kmalloc(sizeof (struct i2c_client) +
sizeof (struct w83781d_data), GFP_KERNEL))) {
err = -ENOMEM;
- goto ERROR0;
+ goto ERROR1;
}
memset(new_client, 0x00, sizeof (struct i2c_client) +
@@ -1108,8 +1217,10 @@
force_*=... parameter, and the Winbond will be reset to the right
bank. */
if (kind < 0) {
- if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80)
- goto ERROR1;
+ if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){
+ err = -ENODEV;
+ goto ERROR2;
+ }
val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
/* Check for Winbond or Asus ID if in bank 0 */
@@ -1117,14 +1228,19 @@
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
&& (val2 != 0x94))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
- && (val2 != 0x06))))
- goto ERROR1;
- /* If Winbond SMBus, check address at 0x48. Asus doesn't support */
+ && (val2 != 0x06)))) {
+ err = -ENODEV;
+ goto ERROR2;
+ }
+ /* If Winbond SMBus, check address at 0x48.
+ Asus doesn't support */
if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
((val1 & 0x80) && (val2 == 0x5c)))) {
if (w83781d_read_value
- (new_client, W83781D_REG_I2C_ADDR) != address)
- goto ERROR1;
+ (new_client, W83781D_REG_I2C_ADDR) != address) {
+ err = -ENODEV;
+ goto ERROR2;
+ }
}
}
@@ -1143,8 +1259,11 @@
vendid = winbond;
else if ((val2 == 0x12) || (val2 == 0x06))
vendid = asus;
- else
- goto ERROR1;
+ else {
+ err = -ENODEV;
+ goto ERROR2;
+ }
+
/* mask off lower bit, not reliable */
val1 =
w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
@@ -1166,38 +1285,31 @@
"Ignoring 'force' parameter for unknown chip at"
"adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address);
- goto ERROR1;
+ err = -EINVAL;
+ goto ERROR2;
}
}
if (kind == w83781d) {
- type_name = "w83781d";
client_name = "W83781D chip";
} else if (kind == w83782d) {
- type_name = "w83782d";
client_name = "W83782D chip";
} else if (kind == w83783s) {
- type_name = "w83783s";
client_name = "W83783S chip";
} else if (kind == w83627hf) {
- type_name = "w83627hf";
client_name = "W83627HF chip";
} else if (kind == as99127f) {
- type_name = "as99127f";
client_name = "AS99127F chip";
} else if (kind == w83697hf) {
- type_name = "w83697hf";
client_name = "W83697HF chip";
} else {
- dev_err(&new_client->dev, "Internal error: unknown kind (%d)?!?", kind);
- goto ERROR1;
+ dev_err(&new_client->dev, "Internal error: unknown "
+ "kind (%d)?!?", kind);
+ err = -ENODEV;
+ goto ERROR2;
}
- /* Reserve the ISA region */
- if (is_isa)
- request_region(address, W83781D_EXTENT, type_name);
-
- /* Fill in the remaining client fields and put it into the global list */
+ /* Fill in the remaining client fields and put into the global list */
strlcpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
data->type = kind;
@@ -1206,76 +1318,13 @@
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
- goto ERROR3;
+ goto ERROR2;
/* attach secondary i2c lm75-like clients */
if (!is_isa) {
- if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
- GFP_KERNEL))) {
- err = -ENOMEM;
- goto ERROR4;
- }
-
- memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
-
- id = i2c_adapter_id(adapter);
- if (force_subclients[0] == id && force_subclients[1] == address) {
- for (i = 2; i <= 3; i++) {
- if (force_subclients[i] < 0x48 ||
- force_subclients[i] > 0x4f) {
- dev_err(&new_client->dev,
- "Invalid subclient address %d; must be 0x48-0x4f\n",
- force_subclients[i]);
- goto ERROR5;
- }
- }
- w83781d_write_value(new_client,
- W83781D_REG_I2C_SUBADDR,
- (force_subclients[2] & 0x07) |
- ((force_subclients[3] & 0x07) <<
- 4));
- data->lm75[0].addr = force_subclients[2];
- } else {
- val1 = w83781d_read_value(new_client,
- W83781D_REG_I2C_SUBADDR);
- data->lm75[0].addr = 0x48 + (val1 & 0x07);
- }
- if (kind != w83783s) {
- if (force_subclients[0] == id &&
- force_subclients[1] == address) {
- data->lm75[1].addr = force_subclients[3];
- } else {
- data->lm75[1].addr =
- 0x48 + ((val1 >> 4) & 0x07);
- }
- if (data->lm75[0].addr == data->lm75[1].addr) {
- dev_err(&new_client->dev,
- "Duplicate addresses 0x%x for subclients.\n",
- data->lm75[0].addr);
- goto ERROR5;
- }
- }
- if (kind == w83781d)
- client_name = "W83781D subclient";
- else if (kind == w83782d)
- client_name = "W83782D subclient";
- else if (kind == w83783s)
- client_name = "W83783S subclient";
- else if (kind == w83627hf)
- client_name = "W83627HF subclient";
- else if (kind == as99127f)
- client_name = "AS99127F subclient";
-
- for (i = 0; i <= 1; i++) {
- i2c_set_clientdata(&data->lm75[i], NULL); /* store all data in w83781d */
- data->lm75[i].adapter = adapter;
- data->lm75[i].driver = &w83781d_driver;
- data->lm75[i].flags = 0;
- strlcpy(data->lm75[i].dev.name, client_name,
- DEVICE_NAME_SIZE);
- if (kind == w83783s)
- break;
- }
+ if ((err = w83781d_detect_subclients(adapter, address,
+ kind, new_client)))
+ goto ERROR3;
} else {
data->lm75 = NULL;
}
@@ -1346,24 +1395,14 @@
w83781d_init_client(new_client);
return 0;
-/* OK, this is not exactly good programming practice, usually. But it is
- very code-efficient in this case. */
-
- ERROR5:
- if (!is_isa) {
- i2c_detach_client(&data->lm75[0]);
- if (data->type != w83783s)
- i2c_detach_client(&data->lm75[1]);
- kfree(data->lm75);
- }
- ERROR4:
+ERROR3:
i2c_detach_client(new_client);
- ERROR3:
+ERROR2:
+ kfree(new_client);
+ERROR1:
if (is_isa)
release_region(address, W83781D_EXTENT);
- ERROR1:
- kfree(new_client);
- ERROR0:
+ERROR0:
return err;
}
@@ -1373,12 +1412,7 @@
struct w83781d_data *data = i2c_get_clientdata(client);
int err;
- if ((err = i2c_detach_client(client))) {
- dev_err(&client->dev,
- "Client deregistration failed, client not detached.\n");
- return err;
- }
-
+ /* release ISA region or I2C subclients first */
if (i2c_is_isa_client(client)) {
release_region(client->addr, W83781D_EXTENT);
} else {
@@ -1387,6 +1421,14 @@
i2c_detach_client(&data->lm75[1]);
kfree(data->lm75);
}
+
+ /* now it's safe to scrap the rest */
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev,
+ "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
kfree(client);
return 0;
diff -urN linux-2.5.70-bk10/drivers/i2c/i2c-core.c linux-2.5.70-bk11/drivers/i2c/i2c-core.c
--- linux-2.5.70-bk10/drivers/i2c/i2c-core.c 2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk11/drivers/i2c/i2c-core.c 2003-06-06 04:38:22.000000000 -0700
@@ -124,7 +124,7 @@
int i2c_del_adapter(struct i2c_adapter *adap)
{
- struct list_head *item;
+ struct list_head *item, *_n;
struct i2c_driver *driver;
struct i2c_client *client;
int res = 0;
@@ -144,7 +144,7 @@
/* detach any active clients. This must be done first, because
* it can fail; in which case we give upp. */
- list_for_each(item,&adap->clients) {
+ list_for_each_safe(item, _n, &adap->clients) {
client = list_entry(item, struct i2c_client, list);
/* detaching devices is unconditional of the set notify
@@ -215,8 +215,7 @@
int i2c_del_driver(struct i2c_driver *driver)
{
- struct list_head *item1;
- struct list_head *item2;
+ struct list_head *item1, *item2, *_n;
struct i2c_client *client;
struct i2c_adapter *adap;
@@ -245,7 +244,7 @@
goto out_unlock;
}
} else {
- list_for_each(item2,&adap->clients) {
+ list_for_each_safe(item2, _n, &adap->clients) {
client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver)
continue;
diff -urN linux-2.5.70-bk10/drivers/ide/Kconfig linux-2.5.70-bk11/drivers/ide/Kconfig
--- linux-2.5.70-bk10/drivers/ide/Kconfig 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/drivers/ide/Kconfig 2003-06-06 04:38:22.000000000 -0700
@@ -268,7 +268,7 @@
config BLK_DEV_IDEPCI
bool "PCI IDE chipset support" if PCI
depends on BLK_DEV_IDE
- default BLK_DEV_IDEDMA_PMAC if ALL_PPC && BLK_DEV_IDEDMA_PMAC
+ default BLK_DEV_IDEDMA_PMAC if PPC_PMAC && BLK_DEV_IDEDMA_PMAC
help
Say Y here for PCI systems which use IDE drive(s).
This option helps the IDE driver to automatically detect and
@@ -409,7 +409,7 @@
bool
depends on BLK_DEV_IDE
default BLK_DEV_IDEDMA_ICS if ARCH_ACORN
- default BLK_DEV_IDEDMA_PMAC if ALL_PPC && BLK_DEV_IDE_PMAC
+ default BLK_DEV_IDEDMA_PMAC if PPC_PMAC && BLK_DEV_IDE_PMAC
default BLK_DEV_IDEDMA_PCI if PCI && BLK_DEV_IDEPCI
config IDEDMA_PCI_WIP
@@ -734,7 +734,7 @@
config BLK_DEV_IDE_PMAC
bool "Builtin PowerMac IDE support"
- depends on BLK_DEV_IDE && ALL_PPC
+ depends on BLK_DEV_IDE && PPC_PMAC
help
This driver provides support for the built-in IDE controller on
most of the recent Apple Power Macintoshes and PowerBooks.
diff -urN linux-2.5.70-bk10/drivers/ide/setup-pci.c linux-2.5.70-bk11/drivers/ide/setup-pci.c
--- linux-2.5.70-bk10/drivers/ide/setup-pci.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/ide/setup-pci.c 2003-06-06 04:38:23.000000000 -0700
@@ -880,7 +880,7 @@
ide_scan_pcidev(dev);
}
} else {
- pci_for_each_dev_reverse(dev) {
+ while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
ide_scan_pcidev(dev);
}
}
diff -urN linux-2.5.70-bk10/drivers/ieee1394/ohci1394.c linux-2.5.70-bk11/drivers/ieee1394/ohci1394.c
--- linux-2.5.70-bk10/drivers/ieee1394/ohci1394.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/ieee1394/ohci1394.c 2003-06-06 04:38:23.000000000 -0700
@@ -111,7 +111,7 @@
#include
#include
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
#include
#include
#include
@@ -3508,7 +3508,7 @@
OHCI1394_REGISTER_SIZE);
#endif
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* On UniNorth, power down the cable and turn off the chip
* clock when the module is removed to save power on
* laptops. Turning it back ON is done by the arch code when
@@ -3522,7 +3522,7 @@
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0);
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
case OHCI_INIT_ALLOC_HOST:
pci_set_drvdata(ohci->dev, NULL);
diff -urN linux-2.5.70-bk10/drivers/macintosh/via-pmu68k.c linux-2.5.70-bk11/drivers/macintosh/via-pmu68k.c
--- linux-2.5.70-bk10/drivers/macintosh/via-pmu68k.c 2003-05-26 18:00:24.000000000 -0700
+++ linux-2.5.70-bk11/drivers/macintosh/via-pmu68k.c 2003-06-06 04:38:23.000000000 -0700
@@ -839,11 +839,11 @@
pbook_pci_save(void)
{
int npci;
- struct pci_dev *pd;
+ struct pci_dev *pd = NULL;
struct pci_save *ps;
npci = 0;
- for (pd = pci_devices; pd != NULL; pd = pd->next)
+ while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL)
++npci;
n_pbook_pci_saves = npci;
if (npci == 0)
@@ -853,7 +853,8 @@
if (ps == NULL)
return;
- for (pd = pci_devices; pd != NULL && npci != 0; pd = pd->next) {
+ pd = NULL;
+ while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
pci_read_config_word(pd, PCI_COMMAND, &ps->command);
pci_read_config_word(pd, PCI_CACHE_LINE_SIZE, &ps->cache_lat);
pci_read_config_word(pd, PCI_INTERRUPT_LINE, &ps->intr);
@@ -867,10 +868,10 @@
{
u16 cmd;
struct pci_save *ps = pbook_pci_saves;
- struct pci_dev *pd;
+ struct pci_dev *pd = NULL;
int j;
- for (pd = pci_devices; pd != NULL; pd = pd->next, ++ps) {
+ while ((pd = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pd)) != NULL) {
if (ps->command == 0)
continue;
pci_read_config_word(pd, PCI_COMMAND, &cmd);
diff -urN linux-2.5.70-bk10/drivers/media/video/Kconfig linux-2.5.70-bk11/drivers/media/video/Kconfig
--- linux-2.5.70-bk10/drivers/media/video/Kconfig 2003-05-26 18:00:58.000000000 -0700
+++ linux-2.5.70-bk11/drivers/media/video/Kconfig 2003-06-06 04:38:23.000000000 -0700
@@ -45,7 +45,7 @@
config VIDEO_PLANB
tristate "PlanB Video-In on PowerMac"
- depends on ALL_PPC && VIDEO_DEV
+ depends on PPC_PMAC && VIDEO_DEV
help
PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
input hardware. If you want to experiment with this, say Y.
diff -urN linux-2.5.70-bk10/drivers/message/fusion/linux_compat.h linux-2.5.70-bk11/drivers/message/fusion/linux_compat.h
--- linux-2.5.70-bk10/drivers/message/fusion/linux_compat.h 2003-05-26 18:00:28.000000000 -0700
+++ linux-2.5.70-bk11/drivers/message/fusion/linux_compat.h 2003-06-06 04:38:23.000000000 -0700
@@ -147,9 +147,7 @@
/* PCI/driver subsystem { */
-#ifndef pci_for_each_dev
-#define pci_for_each_dev(dev) for((dev)=pci_devices; (dev)!=NULL; (dev)=(dev)->next)
-#define pci_peek_next_dev(dev) ((dev)->next ? (dev)->next : NULL)
+#if 0 /* FIXME Don't know what to use to check for the proper kernel version */
#define DEVICE_COUNT_RESOURCE 6
#define PCI_BASEADDR_FLAGS(idx) base_address[idx]
#define PCI_BASEADDR_START(idx) base_address[idx] & ~0xFUL
@@ -169,11 +167,10 @@
(4 - size); \
})
#else
-#define pci_peek_next_dev(dev) ((dev) != pci_dev_g(&pci_devices) ? pci_dev_g((dev)->global_list.next) : NULL)
#define PCI_BASEADDR_FLAGS(idx) resource[idx].flags
#define PCI_BASEADDR_START(idx) resource[idx].start
#define PCI_BASEADDR_SIZE(dev,idx) (dev)->resource[idx].end - (dev)->resource[idx].start + 1
-#endif /* } ifndef pci_for_each_dev */
+#endif /* } ifndef 0 */
/* Compatability for the 2.3.x PCI DMA API. */
diff -urN linux-2.5.70-bk10/drivers/message/fusion/mptbase.c linux-2.5.70-bk11/drivers/message/fusion/mptbase.c
--- linux-2.5.70-bk10/drivers/message/fusion/mptbase.c 2003-06-06 04:38:12.000000000 -0700
+++ linux-2.5.70-bk11/drivers/message/fusion/mptbase.c 2003-06-06 04:38:23.000000000 -0700
@@ -1184,7 +1184,7 @@
* Do some kind of look ahead here...
*/
if (pdev->devfn & 1) {
- pdev2 = pci_peek_next_dev(pdev);
+ pdev2 = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev);
if (pdev2 && (pdev2->vendor == 0x1000) &&
(PCI_SLOT(pdev2->devfn) == PCI_SLOT(pdev->devfn)) &&
(pdev2->device == pdev->device) &&
diff -urN linux-2.5.70-bk10/drivers/net/8139cp.c linux-2.5.70-bk11/drivers/net/8139cp.c
--- linux-2.5.70-bk10/drivers/net/8139cp.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/8139cp.c 2003-06-06 04:38:24.000000000 -0700
@@ -1846,7 +1846,7 @@
}
/* Configure DMA attributes. */
- if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
+ if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
cp->pci_using_dac = 1;
} else {
rc = pci_set_dma_mask(pdev, (u64) 0xffffffff);
diff -urN linux-2.5.70-bk10/drivers/net/Kconfig linux-2.5.70-bk11/drivers/net/Kconfig
--- linux-2.5.70-bk10/drivers/net/Kconfig 2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/Kconfig 2003-06-06 04:38:24.000000000 -0700
@@ -225,7 +225,7 @@
config MACE
tristate "MACE (Power Mac ethernet) support"
- depends on NET_ETHERNET && PPC && ALL_PPC
+ depends on NET_ETHERNET && PPC_PMAC
help
Power Macintoshes and clones with Ethernet built-in on the
motherboard will usually use a MACE (Medium Access Control for
@@ -249,7 +249,7 @@
config BMAC
tristate "BMAC (G3 ethernet) support"
- depends on NET_ETHERNET && PPC && ALL_PPC
+ depends on NET_ETHERNET && PPC_PMAC
help
Say Y for support of BMAC Ethernet interfaces. These are used on G3
computers.
diff -urN linux-2.5.70-bk10/drivers/net/Makefile linux-2.5.70-bk11/drivers/net/Makefile
--- linux-2.5.70-bk10/drivers/net/Makefile 2003-05-26 18:00:27.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/Makefile 2003-06-06 04:38:24.000000000 -0700
@@ -173,7 +173,7 @@
obj-$(CONFIG_TUN) += tun.o
obj-$(CONFIG_DL2K) += dl2k.o
obj-$(CONFIG_R8169) += r8169.o
-obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
+obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o
# non-drivers/net drivers who want mii lib
obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
diff -urN linux-2.5.70-bk10/drivers/net/arcnet/arc-rawmode.c linux-2.5.70-bk11/drivers/net/arcnet/arc-rawmode.c
--- linux-2.5.70-bk10/drivers/net/arcnet/arc-rawmode.c 2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/arcnet/arc-rawmode.c 2003-06-06 04:38:24.000000000 -0700
@@ -45,11 +45,11 @@
struct ArcProto rawmode_proto =
{
- 'r',
- XMTU,
- rx,
- build_header,
- prepare_tx
+ .suffix = 'r',
+ .mtu = XMTU,
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
};
diff -urN linux-2.5.70-bk10/drivers/net/arcnet/arcnet.c linux-2.5.70-bk11/drivers/net/arcnet/arcnet.c
--- linux-2.5.70-bk10/drivers/net/arcnet/arcnet.c 2003-05-26 18:00:43.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/arcnet/arcnet.c 2003-06-06 04:38:24.000000000 -0700
@@ -73,11 +73,11 @@
struct ArcProto arc_proto_null =
{
- '?',
- XMTU,
- null_rx,
- null_build_header,
- null_prepare_tx
+ .suffix = '?',
+ .mtu = XMTU,
+ .rx = null_rx,
+ .build_header = null_build_header,
+ .prepare_tx = null_prepare_tx,
};
static spinlock_t arcnet_lock = SPIN_LOCK_UNLOCKED;
diff -urN linux-2.5.70-bk10/drivers/net/arcnet/rfc1051.c linux-2.5.70-bk11/drivers/net/arcnet/rfc1051.c
--- linux-2.5.70-bk10/drivers/net/arcnet/rfc1051.c 2003-05-26 18:00:42.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/arcnet/rfc1051.c 2003-06-06 04:38:24.000000000 -0700
@@ -45,11 +45,11 @@
struct ArcProto rfc1051_proto =
{
- 's',
- XMTU - RFC1051_HDR_SIZE,
- rx,
- build_header,
- prepare_tx
+ .suffix = 's',
+ .mtu = XMTU - RFC1051_HDR_SIZE,
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
};
diff -urN linux-2.5.70-bk10/drivers/net/arcnet/rfc1201.c linux-2.5.70-bk11/drivers/net/arcnet/rfc1201.c
--- linux-2.5.70-bk10/drivers/net/arcnet/rfc1201.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/arcnet/rfc1201.c 2003-06-06 04:38:24.000000000 -0700
@@ -44,12 +44,12 @@
struct ArcProto rfc1201_proto =
{
- 'a',
- 1500, /* could be more, but some receivers can't handle it... */
- rx,
- build_header,
- prepare_tx,
- continue_tx
+ .suffix = 'a',
+ .mtu = 1500, /* could be more, but some receivers can't handle it... */
+ .rx = rx,
+ .build_header = build_header,
+ .prepare_tx = prepare_tx,
+ .continue_tx = continue_tx,
};
diff -urN linux-2.5.70-bk10/drivers/net/bmac.c linux-2.5.70-bk11/drivers/net/bmac.c
--- linux-2.5.70-bk10/drivers/net/bmac.c 2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/bmac.c 2003-06-06 04:38:24.000000000 -0700
@@ -1331,12 +1331,13 @@
}
}
- dev = init_etherdev(NULL, PRIV_BYTES);
+ dev = alloc_etherdev(PRIV_BYTES);
if (!dev) {
- printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n",
+ printk(KERN_ERR "alloc_etherdev failed, out of memory for BMAC %s\n",
bmac->full_name);
return;
}
+
bp = (struct bmac_data *) dev->priv;
SET_MODULE_OWNER(dev);
bp->node = bmac;
@@ -1344,21 +1345,22 @@
if (!request_OF_resource(bmac, 0, " (bmac)")) {
printk(KERN_ERR "BMAC: can't request IO resource !\n");
- goto err_out;
+ goto out1;
}
if (!request_OF_resource(bmac, 1, " (bmac tx dma)")) {
printk(KERN_ERR "BMAC: can't request TX DMA resource !\n");
- goto err_out;
+ goto out2;
}
-
if (!request_OF_resource(bmac, 2, " (bmac rx dma)")) {
printk(KERN_ERR "BMAC: can't request RX DMA resource !\n");
- goto err_out;
+ goto out3;
}
+
dev->base_addr = (unsigned long)
ioremap(bmac->addrs[0].address, bmac->addrs[0].size);
if (!dev->base_addr)
- goto err_out;
+ goto out4;
+
dev->irq = bmac->intrs[0].line;
bmac_enable_and_reset_chip(dev);
@@ -1429,11 +1431,19 @@
*/
disable_irq(dev->irq);
pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
+
+ if (register_netdev(dev) != 0) {
+ printk(KERN_ERR "registration failed for BMAC %s\n",
+ bmac->full_name);
+ goto err_out_irq2;
+ }
bp->next_bmac = bmac_devs;
bmac_devs = dev;
return;
+err_out_irq2:
+ free_irq(bmac->intrs[2].line, dev);
err_out_irq1:
free_irq(bmac->intrs[1].line, dev);
err_out_irq0:
@@ -1444,14 +1454,14 @@
iounmap((void *)bp->tx_dma);
err_out_iounmap:
iounmap((void *)dev->base_addr);
-err_out:
- if (bp->node) {
- release_OF_resource(bp->node, 0);
- release_OF_resource(bp->node, 1);
- release_OF_resource(bp->node, 2);
- pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
- }
- unregister_netdev(dev);
+out4:
+ release_OF_resource(bp->node, 2);
+out3:
+ release_OF_resource(bp->node, 1);
+out2:
+ release_OF_resource(bp->node, 0);
+out1:
+ pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
kfree(dev);
}
diff -urN linux-2.5.70-bk10/drivers/net/dl2k.h linux-2.5.70-bk11/drivers/net/dl2k.h
--- linux-2.5.70-bk10/drivers/net/dl2k.h 2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/dl2k.h 2003-06-06 04:38:24.000000000 -0700
@@ -243,7 +243,6 @@
VLANTagInsert = 0x0000000010000000,
TFDDone = 0x80000000,
VIDShift = 32,
- CFI = 0x0000100000000000,
UsePriorityShift = 48,
};
diff -urN linux-2.5.70-bk10/drivers/net/hamradio/mkiss.c linux-2.5.70-bk11/drivers/net/hamradio/mkiss.c
--- linux-2.5.70-bk10/drivers/net/hamradio/mkiss.c 2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/hamradio/mkiss.c 2003-06-06 04:38:24.000000000 -0700
@@ -329,6 +329,12 @@
return;
}
ax->rcount -= 2;
+ /* dl9sau bugfix: the trailling two bytes flexnet crc
+ * will not be passed to the kernel. thus we have
+ * to correct the kissparm signature, because it
+ * indicates a crc but there's none
+ */
+ *ax->rbuff &= ~0x20;
}
}
diff -urN linux-2.5.70-bk10/drivers/net/ns83820.c linux-2.5.70-bk11/drivers/net/ns83820.c
--- linux-2.5.70-bk10/drivers/net/ns83820.c 2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/ns83820.c 2003-06-06 04:38:24.000000000 -0700
@@ -1769,7 +1769,7 @@
int using_dac = 0;
/* See if we can set the dma mask early on; failure is fatal. */
- if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffff)) {
+ if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
using_dac = 1;
} else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
using_dac = 0;
diff -urN linux-2.5.70-bk10/drivers/net/pcmcia/fmvj18x_cs.c linux-2.5.70-bk11/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.5.70-bk10/drivers/net/pcmcia/fmvj18x_cs.c 2003-05-26 18:00:43.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/pcmcia/fmvj18x_cs.c 2003-06-06 04:38:24.000000000 -0700
@@ -923,8 +923,7 @@
htons(inw(ioaddr +14)));
lp->stats.tx_errors++;
/* ToDo: We should try to restart the adaptor... */
- cli();
-
+ local_irq_disable();
fjn_reset(dev);
lp->tx_started = 0;
@@ -932,7 +931,7 @@
lp->tx_queue_len = 0;
lp->sent = 0;
lp->open_time = jiffies;
- sti();
+ local_irq_enable();
netif_wake_queue(dev);
}
@@ -1361,9 +1360,8 @@
mc_filter[bit >> 3] |= (1 << bit);
}
}
-
- save_flags(flags);
- cli();
+
+ local_irq_save(flags);
if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
int saved_bank = inb(ioaddr + CONFIG_1);
/* Switch to bank 1 and set the multicast table. */
@@ -1373,5 +1371,5 @@
memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
outb(saved_bank, ioaddr + CONFIG_1);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
diff -urN linux-2.5.70-bk10/drivers/net/sb1000.c linux-2.5.70-bk11/drivers/net/sb1000.c
--- linux-2.5.70-bk10/drivers/net/sb1000.c 2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/sb1000.c 2003-06-06 04:38:24.000000000 -0700
@@ -162,10 +162,17 @@
irq = pnp_irq(pdev, 0);
- if (!request_region(ioaddr[0], 16, dev->name))
+ if (!request_region(ioaddr[0], 16, "sb1000"))
goto out_disable;
- if (!request_region(ioaddr[1], 16, dev->name))
+ if (!request_region(ioaddr[1], 16, "sb1000"))
goto out_release_region0;
+
+ dev = alloc_etherdev(sizeof(struct sb1000_private));
+ if (!dev) {
+ error = -ENOMEM;
+ goto out_release_regions;
+ }
+
dev->base_addr = ioaddr[0];
/* mem_start holds the second I/O address */
@@ -177,12 +184,6 @@
"S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr,
dev->mem_start, serial_number, dev->irq);
- dev = alloc_etherdev(sizeof(struct sb1000_private));
- if (!dev) {
- error = -ENOMEM;
- goto out_release_regions;
- }
-
/*
* The SB1000 is an rx-only cable modem device. The uplink is a modem
* and we do not want to arp on it.
@@ -212,11 +213,9 @@
error = register_netdev(dev);
if (error)
- goto out_unregister;
+ goto out_release_regions;
return 0;
- out_unregister:
- unregister_netdev(dev);
out_release_regions:
release_region(ioaddr[1], 16);
out_release_region0:
@@ -236,6 +235,7 @@
unregister_netdev(dev);
release_region(dev->base_addr, 16);
release_region(dev->mem_start, 16);
+ kfree(dev);
}
static struct pnp_driver sb1000_driver = {
diff -urN linux-2.5.70-bk10/drivers/net/sk98lin/skge.c linux-2.5.70-bk11/drivers/net/sk98lin/skge.c
--- linux-2.5.70-bk10/drivers/net/sk98lin/skge.c 2003-06-06 04:38:13.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/sk98lin/skge.c 2003-06-06 04:38:24.000000000 -0700
@@ -421,7 +421,7 @@
continue;
/* Configure DMA attributes. */
- if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
+ if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
pci_set_dma_mask(pdev, (u64) 0xffffffff))
continue;
diff -urN linux-2.5.70-bk10/drivers/net/sungem.c linux-2.5.70-bk11/drivers/net/sungem.c
--- linux-2.5.70-bk10/drivers/net/sungem.c 2003-05-26 18:00:59.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/sungem.c 2003-06-06 04:38:24.000000000 -0700
@@ -48,7 +48,7 @@
#include
#endif
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
#include
#include
#include
@@ -1491,7 +1491,7 @@
mifcfg &= ~MIF_CFG_BBMODE;
writel(mifcfg, gp->regs + MIF_CFG);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
int i, j;
@@ -1525,7 +1525,7 @@
break;
}
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) {
@@ -1924,7 +1924,7 @@
}
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* Enable the chip's clock and make sure it's config space is
* setup properly. There appear to be no need to restore the
* base addresses.
@@ -1963,7 +1963,7 @@
pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
/* Must be invoked under gp->lock. */
static void gem_stop_phy(struct gem *gp)
@@ -2028,10 +2028,10 @@
spin_unlock_irq(&gp->lock);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* Power down the chip */
gem_apple_powerdown(gp);
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
} else {
gem_stop(gp);
@@ -2085,13 +2085,13 @@
* etc. state so it is safe to do this bit without gp->lock
*/
if (!gp->hw_running) {
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* First, we need to bring up the chip */
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
gem_apple_powerup(gp);
gem_check_invariants(gp);
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
/* Reset the chip */
spin_lock_irq(&gp->lock);
@@ -2112,10 +2112,10 @@
printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
gem_apple_powerdown(gp);
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
/* Fire the PM timer that will shut us down in about 10 seconds */
gp->pm_timer.expires = jiffies + 10*HZ;
add_timer(&gp->pm_timer);
@@ -2227,13 +2227,13 @@
printk(KERN_INFO "%s: resuming\n", dev->name);
if (gp->opened) {
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* First, we need to bring up the chip */
if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
gem_apple_powerup(gp);
gem_check_invariants(gp);
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
spin_lock_irq(&gp->lock);
gem_stop(gp);
@@ -2541,7 +2541,7 @@
return rc;
}
-#if (!defined(__sparc__) && !defined(CONFIG_ALL_PPC))
+#if (!defined(__sparc__) && !defined(CONFIG_PPC))
/* Fetch MAC address from vital product data of PCI ROM. */
static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_addr)
{
@@ -2604,7 +2604,7 @@
static int __devinit gem_get_device_address(struct gem *gp)
{
-#if defined(__sparc__) || defined(CONFIG_ALL_PPC)
+#if defined(__sparc__) || defined(CONFIG_PPC_PMAC)
struct net_device *dev = gp->dev;
#endif
@@ -2623,7 +2623,7 @@
}
if (node == -1)
memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
-#elif defined(CONFIG_ALL_PPC)
+#elif defined(CONFIG_PPC_PMAC)
unsigned char *addr;
addr = get_property(gp->of_node, "local-mac-address", NULL);
@@ -2748,7 +2748,7 @@
* invariants to work, but also because the firmware might
* not have properly shut down the PHY.
*/
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
if (pdev->vendor == PCI_VENDOR_ID_APPLE)
gem_apple_powerup(gp);
#endif
@@ -2779,7 +2779,7 @@
goto err_out_iounmap;
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
gp->of_node = pci_device_to_OF_node(pdev);
#endif
if (gem_get_device_address(gp))
diff -urN linux-2.5.70-bk10/drivers/net/sungem.h linux-2.5.70-bk11/drivers/net/sungem.h
--- linux-2.5.70-bk10/drivers/net/sungem.h 2003-05-26 18:00:41.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/sungem.h 2003-06-06 04:38:24.000000000 -0700
@@ -998,7 +998,7 @@
dma_addr_t gblock_dvma;
struct pci_dev *pdev;
struct net_device *dev;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
struct device_node *of_node;
#endif
};
diff -urN linux-2.5.70-bk10/drivers/net/sunqe.c linux-2.5.70-bk11/drivers/net/sunqe.c
--- linux-2.5.70-bk10/drivers/net/sunqe.c 2003-06-06 04:38:13.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/sunqe.c 2003-06-06 04:38:24.000000000 -0700
@@ -722,34 +722,31 @@
struct net_device *qe_devs[4];
struct sunqe *qeps[4];
struct sbus_dev *qesdevs[4];
+ struct sbus_dev *child;
struct sunqec *qecp = NULL;
u8 bsizes, bsizes_more;
- int i, j, res = ENOMEM;
+ int i, j, res = -ENOMEM;
- dev = init_etherdev(0, sizeof(struct sunqe));
- qe_devs[0] = dev;
- qeps[0] = (struct sunqe *) dev->priv;
- qeps[0]->channel = 0;
- spin_lock_init(&qeps[0]->lock);
- for (j = 0; j < 6; j++)
- qe_devs[0]->dev_addr[j] = idprom->id_ethaddr[j];
+ for (i = 0; i < 4; i++) {
+ qe_devs[i] = alloc_etherdev(sizeof(struct sunqe));
+ if (!qe_devs[i])
+ goto out;
+ }
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
- qe_devs[1] = qe_devs[2] = qe_devs[3] = NULL;
- for (i = 1; i < 4; i++) {
- qe_devs[i] = init_etherdev(0, sizeof(struct sunqe));
- if (qe_devs[i] == NULL || qe_devs[i]->priv == NULL)
- goto qec_free_devs;
+ for (i = 0; i < 4; i++) {
qeps[i] = (struct sunqe *) qe_devs[i]->priv;
for (j = 0; j < 6; j++)
qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j];
qeps[i]->channel = i;
+ spin_lock_init(&qeps[i]->lock);
}
+
qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL);
if (qecp == NULL)
- goto qec_free_devs;
+ goto out1;
qecp->qec_sdev = sdev;
for (i = 0; i < 4; i++) {
@@ -758,25 +755,15 @@
qeps[i]->parent = qecp;
}
- /* Link in channel 0. */
- i = prom_getintdefault(sdev->child->prom_node, "channel#", -1);
- if (i == -1) { res=ENODEV; goto qec_free_devs; }
- qesdevs[i] = sdev->child;
-
- /* Link in channel 1. */
- i = prom_getintdefault(sdev->child->next->prom_node, "channel#", -1);
- if (i == -1) { res=ENODEV; goto qec_free_devs; }
- qesdevs[i] = sdev->child->next;
-
- /* Link in channel 2. */
- i = prom_getintdefault(sdev->child->next->next->prom_node, "channel#", -1);
- if (i == -1) { res=ENODEV; goto qec_free_devs; }
- qesdevs[i] = sdev->child->next->next;
-
- /* Link in channel 3. */
- i = prom_getintdefault(sdev->child->next->next->next->prom_node, "channel#", -1);
- if (i == -1) { res=ENODEV; goto qec_free_devs; }
- qesdevs[i] = sdev->child->next->next->next;
+ res = -ENODEV;
+
+ for (i = 0, child = sdev->child; i < 4; i++, child = child->next) {
+ /* Link in channel */
+ j = prom_getintdefault(child->prom_node, "channel#", -1);
+ if (j == -1)
+ goto out2;
+ qesdevs[j] = child;
+ }
for (i = 0; i < 4; i++)
qeps[i]->qe_sdev = qesdevs[i];
@@ -786,22 +773,18 @@
GLOB_REG_SIZE, "QEC Global Registers");
if (!qecp->gregs) {
printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n");
- res = ENODEV;
- goto qec_free_devs;
+ goto out2;
}
/* Make sure the QEC is in MACE mode. */
if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) {
printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n");
- res = ENODEV;
- goto qec_free_devs;
+ goto out3;
}
/* Reset the QEC. */
- if (qec_global_reset(qecp->gregs)) {
- res = ENODEV;
- goto qec_free_devs;
- }
+ if (qec_global_reset(qecp->gregs))
+ goto out3;
/* Find and set the burst sizes for the QEC, since it does
* the actual dma for all 4 channels.
@@ -824,40 +807,36 @@
qec_init_once(qecp, sdev);
for (i = 0; i < 4; i++) {
+ struct sunqe *qe = qeps[i];
/* Map in QEC per-channel control registers. */
- qeps[i]->qcregs = sbus_ioremap(&qesdevs[i]->resource[0], 0,
- CREG_REG_SIZE, "QEC Channel Registers");
- if (!qeps[i]->qcregs) {
+ qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0,
+ CREG_REG_SIZE, "QEC Channel Registers");
+ if (!qe->qcregs) {
printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i);
- res = ENODEV;
- goto qec_free_devs;
+ goto out4;
}
/* Map in per-channel AMD MACE registers. */
- qeps[i]->mregs = sbus_ioremap(&qesdevs[i]->resource[1], 0,
- MREGS_REG_SIZE, "QE MACE Registers");
- if (!qeps[i]->mregs) {
+ qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0,
+ MREGS_REG_SIZE, "QE MACE Registers");
+ if (!qe->mregs) {
printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i);
- res = ENODEV;
- goto qec_free_devs;
+ goto out4;
}
- qeps[i]->qe_block = sbus_alloc_consistent(qesdevs[i],
- PAGE_SIZE,
- &qeps[i]->qblock_dvma);
- qeps[i]->buffers = sbus_alloc_consistent(qesdevs[i],
- sizeof(struct sunqe_buffers),
- &qeps[i]->buffers_dvma);
- if (qeps[i]->qe_block == NULL ||
- qeps[i]->qblock_dvma == 0 ||
- qeps[i]->buffers == NULL ||
- qeps[i]->buffers_dvma == 0) {
- res = ENODEV;
- goto qec_free_devs;
+ qe->qe_block = sbus_alloc_consistent(qe->qe_sdev,
+ PAGE_SIZE,
+ &qe->qblock_dvma);
+ qe->buffers = sbus_alloc_consistent(qe->qe_sdev,
+ sizeof(struct sunqe_buffers),
+ &qe->buffers_dvma);
+ if (qe->qe_block == NULL || qe->qblock_dvma == 0 ||
+ qe->buffers == NULL || qe->buffers_dvma == 0) {
+ goto out4;
}
/* Stop this QE. */
- qe_stop(qeps[i]);
+ qe_stop(qe);
}
for (i = 0; i < 4; i++) {
@@ -871,7 +850,6 @@
qe_devs[i]->watchdog_timeo = 5*HZ;
qe_devs[i]->irq = sdev->irqs[0];
qe_devs[i]->dma = 0;
- ether_setup(qe_devs[i]);
}
/* QEC receives interrupts from each QE, then it sends the actual
@@ -882,8 +860,13 @@
if (request_irq(sdev->irqs[0], &qec_interrupt,
SA_SHIRQ, "QuadEther", (void *) qecp)) {
printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n");
- res = EAGAIN;
- goto qec_free_devs;
+ res = -EAGAIN;
+ goto out4;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (register_netdev(qe_devs[i]) != 0)
+ goto out5;
}
/* Report the QE channels. */
@@ -899,42 +882,43 @@
/* We are home free at this point, link the qe's into
* the master list for later driver exit.
*/
- for (i = 0; i < 4; i++)
- qe_devs[i]->ifindex = dev_new_index();
qecp->next_module = root_qec_dev;
root_qec_dev = qecp;
return 0;
-qec_free_devs:
+out5:
+ while (i--)
+ unregister_netdev(qe_devs[i]);
+ free_irq(sdev->irqs[0], (void *)qecp);
+out4:
for (i = 0; i < 4; i++) {
- if (qe_devs[i] != NULL) {
- if (qe_devs[i]->priv) {
- struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv;
-
- if (qe->qcregs)
- sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
- if (qe->mregs)
- sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
- if (qe->qe_block != NULL)
- sbus_free_consistent(qe->qe_sdev,
- PAGE_SIZE,
- qe->qe_block,
- qe->qblock_dvma);
- if (qe->buffers != NULL)
- sbus_free_consistent(qe->qe_sdev,
- sizeof(struct sunqe_buffers),
- qe->buffers,
- qe->buffers_dvma);
- }
- kfree(qe_devs[i]);
- }
- }
- if (qecp != NULL) {
- if (qecp->gregs)
- sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
- kfree(qecp);
+ struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv;
+
+ if (qe->qcregs)
+ sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
+ if (qe->mregs)
+ sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
+ if (qe->qe_block)
+ sbus_free_consistent(qe->qe_sdev,
+ PAGE_SIZE,
+ qe->qe_block,
+ qe->qblock_dvma);
+ if (qe->buffers)
+ sbus_free_consistent(qe->qe_sdev,
+ sizeof(struct sunqe_buffers),
+ qe->buffers,
+ qe->buffers_dvma);
}
+out3:
+ sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
+out2:
+ kfree(qecp);
+out1:
+ i = 4;
+out:
+ while (i--)
+ kfree(qe_devs[i]);
return res;
}
diff -urN linux-2.5.70-bk10/drivers/net/tg3.c linux-2.5.70-bk11/drivers/net/tg3.c
--- linux-2.5.70-bk10/drivers/net/tg3.c 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/tg3.c 2003-06-06 04:38:24.000000000 -0700
@@ -6740,7 +6740,7 @@
}
/* Configure DMA attributes. */
- if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
+ if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
pci_using_dac = 1;
if (pci_set_consistent_dma_mask(pdev,
(u64) 0xffffffffffffffff)) {
diff -urN linux-2.5.70-bk10/drivers/net/tun.c linux-2.5.70-bk11/drivers/net/tun.c
--- linux-2.5.70-bk10/drivers/net/tun.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/tun.c 2003-06-06 04:38:24.000000000 -0700
@@ -551,10 +551,12 @@
if (!(tun->flags & TUN_PERSIST)) {
dev_close(&tun->dev);
unregister_netdevice(&tun->dev);
- kfree(tun);
}
rtnl_unlock();
+
+ if (!(tun->flags & TUN_PERSIST))
+ kfree(tun);
return 0;
}
diff -urN linux-2.5.70-bk10/drivers/net/wireless/Kconfig linux-2.5.70-bk11/drivers/net/wireless/Kconfig
--- linux-2.5.70-bk10/drivers/net/wireless/Kconfig 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/wireless/Kconfig 2003-06-06 04:38:24.000000000 -0700
@@ -149,7 +149,7 @@
unsure, say N.
comment "Wireless 802.11b ISA/PCI cards support"
- depends on NET_RADIO && (ISA || PCI || ALL_PPC || PCMCIA)
+ depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
@@ -169,7 +169,7 @@
config HERMES
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
- depends on NET_RADIO && (ALL_PPC || PCI || PCMCIA)
+ depends on NET_RADIO && (PPC_PMAC || PCI || PCMCIA)
---help---
A driver for 802.11b wireless cards based based on the "Hermes" or
Intersil HFA384x (Prism 2) MAC controller. This includes the vast
@@ -191,7 +191,7 @@
config APPLE_AIRPORT
tristate "Apple Airport support (built-in)"
- depends on ALL_PPC && HERMES
+ depends on PPC_PMAC && HERMES
help
Say Y here to support the Airport 802.11b wireless Ethernet hardware
built into the Macintosh iBook and other recent PowerPC-based
@@ -281,10 +281,25 @@
for location). You also want to check out the PCMCIA-HOWTO,
available from .
+config PCMCIA_ATMEL
+ tristate "Atmel at76c502/at76c504 PCMCIA cards"
+ depends on NET_RADIO && EXPERIMENTAL && PCMCIA
+ ---help---
+ A driver for PCMCIA 802.11 wireless cards based on the
+ Atmel fast-vnet chips. This driver supports standard
+ Linux wireless extensions.
+
+ Many cards based on this chipset do not have flash memory
+ and need their firmware loaded at start-up. If yours is
+ one of these, you will need to provide a firmware image
+ to be loaded into the card by the driver. The Atmel
+ firmware package can be downloaded from
+ http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
+
# yes, this works even when no drivers are selected
config NET_WIRELESS
bool
- depends on NET_RADIO && (ISA || PCI || ALL_PPC || PCMCIA)
+ depends on NET_RADIO && (ISA || PCI || PPC_PMAC || PCMCIA)
default y
endmenu
diff -urN linux-2.5.70-bk10/drivers/net/wireless/Makefile linux-2.5.70-bk11/drivers/net/wireless/Makefile
--- linux-2.5.70-bk10/drivers/net/wireless/Makefile 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/net/wireless/Makefile 2003-06-06 04:38:24.000000000 -0700
@@ -22,4 +22,5 @@
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
+obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o atmel.o
diff -urN linux-2.5.70-bk10/drivers/net/wireless/atmel.c linux-2.5.70-bk11/drivers/net/wireless/atmel.c
--- linux-2.5.70-bk10/drivers/net/wireless/atmel.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk11/drivers/net/wireless/atmel.c 2003-06-06 04:38:24.000000000 -0700
@@ -0,0 +1,3943 @@
+/*** -*- linux-c -*- **********************************************************
+
+ Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+ Copyright 2000-2001 ATMEL Corporation.
+ Copyright 2003 Simon Kelley.
+
+ This code was developed from version 2.1.1 of the Atmel drivers,
+ released by Atmel corp. under the GPL in December 2002. It also
+ includes code from the Linux aironet drivers (C) Benjamin Reed,
+ and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
+ extensions, (C) Jean Tourrilhes.
+
+ The firmware module for reading the MAC address of the card comes from
+ net.russotto.AtmelMACFW, written by Matthew T. Russotto and copyright
+ by him. net.russotto.AtmelMACFW is used under the GPL license version 2.
+ This file contains the module in binary form and, under the terms
+ of the GPL, in source form. The source is located at the end of the file.
+
+ For all queries about this code, please contact the current author,
+ Simon Kelley and not Atmel Corporation.
+
+ 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************************************************************************/
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef CONFIG_FW_LOADER
+#include
+#endif
+#include "ieee802_11.h"
+
+#define DRIVER_MAJOR 0
+#define DRIVER_MINOR 7
+
+MODULE_AUTHOR("Simon Kelley");
+MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
+
+/* The name of the firmware file to be loaded
+ over-rides any automatic selection */
+static char *firmware = NULL;
+module_param(firmware, charp, 0);
+
+#define MAX_SSID_LENGTH 32
+#define MGMT_JIFFIES (256 * HZ / 100)
+
+#define MAX_BSS_ENTRIES 64
+
+/* registers */
+#define GCR 0x00 // (SIR0) General Configuration Register
+#define BSR 0x02 // (SIR1) Bank Switching Select Register
+#define AR 0x04
+#define DR 0x08
+#define MR1 0x12 // Mirror Register 1
+#define MR2 0x14 // Mirror Register 2
+#define MR3 0x16 // Mirror Register 3
+#define MR4 0x18 // Mirror Register 4
+
+#define GPR1 0x0c
+#define GPR2 0x0e
+#define GPR3 0x10
+//
+// Constants for the GCR register.
+//
+#define GCR_REMAP 0x0400 // Remap internal SRAM to 0
+#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset)
+#define GCR_CORES 0x0060 // Core Reset (ARM and PAI are reset)
+#define GCR_ENINT 0x0002 // Enable Interrupts
+#define GCR_ACKINT 0x0008 // Acknowledge Interrupts
+
+#define BSS_SRAM 0x0200 // AMBA module selection --> SRAM
+#define BSS_IRAM 0x0100 // AMBA module selection --> IRAM
+//
+// Constants for the MR registers.
+//
+#define MAC_INIT_COMPLETE 0x0001 // MAC init has been completed
+#define MAC_BOOT_COMPLETE 0x0010 // MAC boot has been completed
+#define MAC_INIT_OK 0x0002 // MAC boot has been completed
+
+#define C80211_SUBTYPE_MGMT_ASS_REQUEST 0x00
+#define C80211_SUBTYPE_MGMT_ASS_RESPONSE 0x10
+#define C80211_SUBTYPE_MGMT_REASS_REQUEST 0x20
+#define C80211_SUBTYPE_MGMT_REASS_RESPONSE 0x30
+#define C80211_SUBTYPE_MGMT_ProbeRequest 0x40
+#define C80211_SUBTYPE_MGMT_ProbeResponse 0x50
+#define C80211_SUBTYPE_MGMT_BEACON 0x80
+#define C80211_SUBTYPE_MGMT_ATIM 0x90
+#define C80211_SUBTYPE_MGMT_DISASSOSIATION 0xA0
+#define C80211_SUBTYPE_MGMT_Authentication 0xB0
+#define C80211_SUBTYPE_MGMT_Deauthentication 0xC0
+
+#define C80211_MGMT_AAN_OPENSYSTEM 0x0000
+#define C80211_MGMT_AAN_SHAREDKEY 0x0001
+
+#define C80211_MGMT_CAPABILITY_ESS 0x0001 // see 802.11 p.58
+#define C80211_MGMT_CAPABILITY_IBSS 0x0002 // - " -
+#define C80211_MGMT_CAPABILITY_CFPollable 0x0004 // - " -
+#define C80211_MGMT_CAPABILITY_CFPollRequest 0x0008 // - " -
+#define C80211_MGMT_CAPABILITY_Privacy 0x0010 // - " -
+
+#define C80211_MGMT_SC_Success 0
+#define C80211_MGMT_SC_Unspecified 1
+#define C80211_MGMT_SC_SupportCapabilities 10
+#define C80211_MGMT_SC_ReassDenied 11
+#define C80211_MGMT_SC_AssDenied 12
+#define C80211_MGMT_SC_AuthAlgNotSupported 13
+#define C80211_MGMT_SC_AuthTransSeqNumError 14
+#define C80211_MGMT_SC_AuthRejectChallenge 15
+#define C80211_MGMT_SC_AuthRejectTimeout 16
+#define C80211_MGMT_SC_AssDeniedHandleAP 17
+#define C80211_MGMT_SC_AssDeniedBSSRate 18
+
+#define C80211_MGMT_ElementID_SSID 0
+#define C80211_MGMT_ElementID_SupportedRates 1
+#define C80211_MGMT_ElementID_ChallengeText 16
+#define C80211_MGMT_CAPABILITY_ShortPreamble 0x0020
+
+struct get_set_mib {
+ u8 type;
+ u8 size;
+ u8 index;
+ u8 reserved;
+ u8 data[72];
+};
+
+struct rx_desc {
+ u32 Next;
+ u16 MsduPos;
+ u16 MsduSize;
+
+ u8 State;
+ u8 Status;
+ u8 Rate;
+ u8 Rssi;
+ u8 LinkQuality;
+ u8 PreambleType;
+ u16 Duration;
+ u32 RxTime;
+
+};
+
+#define RX_DESC_FLAG_VALID 0x80
+#define RX_DESC_FLAG_CONSUMED 0x40
+#define RX_DESC_FLAG_IDLE 0x00
+
+#define RX_STATUS_SUCCESS 0x00
+
+#define RX_DESC_MSDU_POS_OFFSET 4
+#define RX_DESC_MSDU_SIZE_OFFSET 6
+#define RX_DESC_FLAGS_OFFSET 8
+#define RX_DESC_STATUS_OFFSET 9
+#define RX_DESC_RSSI_OFFSET 11
+#define RX_DESC_LINK_QUALITY_OFFSET 12
+#define RX_DESC_PREAMBLE_TYPE_OFFSET 13
+#define RX_DESC_DURATION_OFFSET 14
+#define RX_DESC_RX_TIME_OFFSET 16
+
+
+struct tx_desc {
+ u32 NextDescriptor;
+ u16 TxStartOfFrame;
+ u16 TxLength;
+
+ u8 TxState;
+ u8 TxStatus;
+ u8 RetryCount;
+
+ u8 TxRate;
+ u32 TxTime;
+ u8 Reserved;
+ u8 PacketType;
+ u16 HostTxLength;
+
+};
+
+
+#define TX_DESC_NEXT_OFFSET 0
+#define TX_DESC_POS_OFFSET 4
+#define TX_DESC_SIZE_OFFSET 6
+#define TX_DESC_FLAGS_OFFSET 8
+#define TX_DESC_STATUS_OFFSET 9
+#define TX_DESC_RETRY_OFFSET 10
+#define TX_DESC_RATE_OFFSET 11
+#define TX_DESC_PACKET_TYPE_OFFSET 17
+#define TX_DESC_HOST_LENGTH_OFFSET 18
+
+
+
+///////////////////////////////////////////////////////
+// Host-MAC interface
+///////////////////////////////////////////////////////
+
+#define TX_STATUS_SUCCESS 0x00
+
+#define TX_FIRM_OWN 0x80
+#define TX_DONE 0x40
+
+
+#define TX_ERROR 0x01
+
+#define TX_PACKET_TYPE_DATA 0x01
+#define TX_PACKET_TYPE_MGMT 0x02
+
+#define ISR_EMPTY 0x00 // no bits set in ISR
+#define ISR_TxCOMPLETE 0x01 // packet transmitted
+#define ISR_RxCOMPLETE 0x02 // packet received
+#define ISR_RxFRAMELOST 0x04 // Rx Frame lost
+#define ISR_FATAL_ERROR 0x08 // Fatal error
+#define ISR_COMMAND_COMPLETE 0x10 // command completed
+#define ISR_OUT_OF_RANGE 0x20 // command completed
+#define ISR_IBSS_MERGE 0x40 // (4.1.2.30): IBSS merge
+#define ISR_GENERIC_IRQ 0x80
+
+
+#define Local_Mib_Type 0x01
+#define Mac_Address_Mib_Type 0x02
+#define Mac_Mib_Type 0x03
+#define Statistics_Mib_Type 0x04
+#define Mac_Mgmt_Mib_Type 0x05
+#define Mac_Wep_Mib_Type 0x06
+#define Phy_Mib_Type 0x07
+#define Multi_Domain_MIB 0x08
+
+#define MAC_MGMT_MIB_CUR_BSSID_POS 14
+#define MAC_MIB_FRAG_THRESHOLD_POS 8
+#define MAC_MIB_RTS_THRESHOLD_POS 10
+#define MAC_MIB_SHORT_RETRY_POS 16
+#define MAC_MIB_LONG_RETRY_POS 17
+#define MAC_MIB_SHORT_RETRY_LIMIT_POS 16
+#define MAC_MGMT_MIB_BEACON_PER_POS 0
+#define MAC_MGMT_MIB_STATION_ID_POS 6
+#define MAC_MGMT_MIB_CUR_PRIVACY_POS 11
+#define MAC_MGMT_MIB_CUR_BSSID_POS 14
+#define MAC_MGMT_MIB_PS_MODE_POS 53
+#define MAC_MGMT_MIB_LISTEN_INTERVAL_POS 54
+#define MAC_MGMT_MIB_MULTI_DOMAIN_IMPLEMENTED 56
+#define MAC_MGMT_MIB_MULTI_DOMAIN_ENABLED 57
+#define PHY_MIB_CHANNEL_POS 14
+#define PHY_MIB_RATE_SET_POS 20
+#define PHY_MIB_REG_DOMAIN_POS 26
+#define LOCAL_MIB_AUTO_TX_RATE_POS 3
+#define LOCAL_MIB_SSID_SIZE 5
+#define LOCAL_MIB_TX_PROMISCUOUS_POS 6
+#define LOCAL_MIB_TX_MGMT_RATE_POS 7
+#define LOCAL_MIB_TX_CONTROL_RATE_POS 8
+#define LOCAL_MIB_PREAMBLE_TYPE 9
+#define MAC_ADDR_MIB_MAC_ADDR_POS 0
+
+
+#define CMD_Set_MIB_Vars 0x01
+#define CMD_Get_MIB_Vars 0x02
+#define CMD_Scan 0x03
+#define CMD_Join 0x04
+#define CMD_Start 0x05
+#define CMD_EnableRadio 0x06
+#define CMD_DisableRadio 0x07
+#define CMD_SiteSurvey 0x0B
+
+#define CMD_STATUS_IDLE 0x00
+#define CMD_STATUS_COMPLETE 0x01
+#define CMD_STATUS_UNKNOWN 0x02
+#define CMD_STATUS_INVALID_PARAMETER 0x03
+#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
+#define CMD_STATUS_TIME_OUT 0x07
+#define CMD_STATUS_IN_PROGRESS 0x08
+#define CMD_STATUS_REJECTED_RADIO_OFF 0x09
+#define CMD_STATUS_HOST_ERROR 0xFF
+#define CMD_STATUS_BUSY 0xFE
+
+
+#define CMD_BLOCK_COMMAND_OFFSET 0
+#define CMD_BLOCK_STATUS_OFFSET 1
+#define CMD_BLOCK_PARAMETERS_OFFSET 4
+
+#define SCAN_OPTIONS_SITE_SURVEY 0x80
+
+#define MGMT_FRAME_BODY_OFFSET 24
+#define MAX_AUTHENTICATION_RETRIES 3
+#define MAX_ASSOCIATION_RETRIES 3
+
+#define AUTHENTICATION_RESPONSE_TIME_OUT 1000
+
+#define MAX_WIRELESS_BODY 2316 /* mtu is 2312, CRC is 4 */
+#define LOOP_RETRY_LIMIT 500000
+
+#define ACTIVE_MODE 1
+#define PS_MODE 2
+
+///////////////////////////////////////////////////////////////////////////
+// 802.11 related definitions
+///////////////////////////////////////////////////////////////////////////
+
+//
+// Regulatory Domains
+//
+
+#define REG_DOMAIN_FCC 0x10 //Channels 1-11 USA
+#define REG_DOMAIN_DOC 0x20 //Channel 1-11 Canada
+#define REG_DOMAIN_ETSI 0x30 //Channel 1-13 Europe (ex Spain/France)
+#define REG_DOMAIN_SPAIN 0x31 //Channel 10-11 Spain
+#define REG_DOMAIN_FRANCE 0x32 //Channel 10-13 France
+#define REG_DOMAIN_MKK 0x40 //Channel 14 Japan
+#define REG_DOMAIN_MKK1 0x41 //Channel 1-14 Japan(MKK1)
+#define REG_DOMAIN_ISRAEL 0x50 //Channel 3-9 ISRAEL
+
+#define BSS_TYPE_AD_HOC 1
+#define BSS_TYPE_INFRASTRUCTURE 2
+
+#define SCAN_TYPE_ACTIVE 0
+#define SCAN_TYPE_PASSIVE 1
+
+#define LONG_PREAMBLE 0
+#define SHORT_PREAMBLE 1
+#define AUTO_PREAMBLE 2
+
+#define DATA_FRAME_WS_HEADER_SIZE 30
+
+/* promiscuous mode control */
+#define PROM_MODE_OFF 0x0
+#define PROM_MODE_UNKNOWN 0x1
+#define PROM_MODE_CRC_FAILED 0x2
+#define PROM_MODE_DUPLICATED 0x4
+#define PROM_MODE_MGMT 0x8
+#define PROM_MODE_CTRL 0x10
+#define PROM_MODE_BAD_PROTOCOL 0x20
+
+
+#define IFACE_INT_STATUS_OFFSET 0
+#define IFACE_INT_MASK_OFFSET 1
+#define IFACE_LOCKOUT_HOST_OFFSET 2
+#define IFACE_LOCKOUT_MAC_OFFSET 3
+#define IFACE_FUNC_CTRL_OFFSET 28
+#define IFACE_MAC_STAT_OFFSET 30
+#define IFACE_GENERIC_INT_TYPE_OFFSET 32
+//
+// IFACE MACROS & definitions
+//
+//
+
+// FuncCtrl field:
+//
+#define FUNC_CTRL_TxENABLE 0x10
+#define FUNC_CTRL_RxENABLE 0x20
+#define FUNC_CTRL_INIT_COMPLETE 0x01
+
+/* A stub firmware image which reads the MAC address from NVRAM on the card.
+ For copyright information and source see the end of this file. */
+static u8 mac_reader[] = {
+ 0x06,0x00,0x00,0xea,0x04,0x00,0x00,0xea,0x03,0x00,0x00,0xea,0x02,0x00,0x00,0xea,
+ 0x01,0x00,0x00,0xea,0x00,0x00,0x00,0xea,0xff,0xff,0xff,0xea,0xfe,0xff,0xff,0xea,
+ 0xd3,0x00,0xa0,0xe3,0x00,0xf0,0x21,0xe1,0x0e,0x04,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+ 0x81,0x11,0xa0,0xe1,0x00,0x10,0x81,0xe3,0x00,0x10,0x80,0xe5,0x1c,0x10,0x90,0xe5,
+ 0x10,0x10,0xc1,0xe3,0x1c,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,0x08,0x10,0x80,0xe5,
+ 0x02,0x03,0xa0,0xe3,0x00,0x10,0xa0,0xe3,0xb0,0x10,0xc0,0xe1,0xb4,0x10,0xc0,0xe1,
+ 0xb8,0x10,0xc0,0xe1,0xbc,0x10,0xc0,0xe1,0x56,0xdc,0xa0,0xe3,0x21,0x00,0x00,0xeb,
+ 0x0a,0x00,0xa0,0xe3,0x1a,0x00,0x00,0xeb,0x10,0x00,0x00,0xeb,0x07,0x00,0x00,0xeb,
+ 0x02,0x03,0xa0,0xe3,0x02,0x14,0xa0,0xe3,0xb4,0x10,0xc0,0xe1,0x4c,0x10,0x9f,0xe5,
+ 0xbc,0x10,0xc0,0xe1,0x10,0x10,0xa0,0xe3,0xb8,0x10,0xc0,0xe1,0xfe,0xff,0xff,0xea,
+ 0x00,0x40,0x2d,0xe9,0x00,0x20,0xa0,0xe3,0x02,0x3c,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+ 0x28,0x00,0x9f,0xe5,0x37,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,
+ 0x00,0x40,0x2d,0xe9,0x12,0x2e,0xa0,0xe3,0x06,0x30,0xa0,0xe3,0x00,0x10,0xa0,0xe3,
+ 0x02,0x04,0xa0,0xe3,0x2f,0x00,0x00,0xeb,0x00,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,
+ 0x00,0x02,0x00,0x02,0x80,0x01,0x90,0xe0,0x01,0x00,0x00,0x0a,0x01,0x00,0x50,0xe2,
+ 0xfc,0xff,0xff,0xea,0x1e,0xff,0x2f,0xe1,0x80,0x10,0xa0,0xe3,0xf3,0x06,0xa0,0xe3,
+ 0x00,0x10,0x80,0xe5,0x00,0x10,0xa0,0xe3,0x00,0x10,0x80,0xe5,0x01,0x10,0xa0,0xe3,
+ 0x04,0x10,0x80,0xe5,0x00,0x10,0x80,0xe5,0x0e,0x34,0xa0,0xe3,0x1c,0x10,0x93,0xe5,
+ 0x02,0x1a,0x81,0xe3,0x1c,0x10,0x83,0xe5,0x58,0x11,0x9f,0xe5,0x30,0x10,0x80,0xe5,
+ 0x54,0x11,0x9f,0xe5,0x34,0x10,0x80,0xe5,0x38,0x10,0x80,0xe5,0x3c,0x10,0x80,0xe5,
+ 0x10,0x10,0x90,0xe5,0x08,0x00,0x90,0xe5,0x1e,0xff,0x2f,0xe1,0xf3,0x16,0xa0,0xe3,
+ 0x08,0x00,0x91,0xe5,0x05,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,0x10,0x00,0x91,0xe5,
+ 0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0xff,0x00,0xa0,0xe3,0x0c,0x00,0x81,0xe5,
+ 0x10,0x00,0x91,0xe5,0x02,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5,
+ 0x10,0x00,0x91,0xe5,0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x91,0xe5,
+ 0xff,0x00,0x00,0xe2,0x1e,0xff,0x2f,0xe1,0x30,0x40,0x2d,0xe9,0x00,0x50,0xa0,0xe1,
+ 0x03,0x40,0xa0,0xe1,0xa2,0x02,0xa0,0xe1,0x08,0x00,0x00,0xe2,0x03,0x00,0x80,0xe2,
+ 0xd8,0x10,0x9f,0xe5,0x00,0x00,0xc1,0xe5,0x01,0x20,0xc1,0xe5,0xe2,0xff,0xff,0xeb,
+ 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x1a,0x14,0x00,0xa0,0xe3,0xc4,0xff,0xff,0xeb,
+ 0x04,0x20,0xa0,0xe1,0x05,0x10,0xa0,0xe1,0x02,0x00,0xa0,0xe3,0x01,0x00,0x00,0xeb,
+ 0x30,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x70,0x40,0x2d,0xe9,0xf3,0x46,0xa0,0xe3,
+ 0x00,0x30,0xa0,0xe3,0x00,0x00,0x50,0xe3,0x08,0x00,0x00,0x9a,0x8c,0x50,0x9f,0xe5,
+ 0x03,0x60,0xd5,0xe7,0x0c,0x60,0x84,0xe5,0x10,0x60,0x94,0xe5,0x02,0x00,0x16,0xe3,
+ 0xfc,0xff,0xff,0x0a,0x01,0x30,0x83,0xe2,0x00,0x00,0x53,0xe1,0xf7,0xff,0xff,0x3a,
+ 0xff,0x30,0xa0,0xe3,0x0c,0x30,0x84,0xe5,0x08,0x00,0x94,0xe5,0x10,0x00,0x94,0xe5,
+ 0x01,0x00,0x10,0xe3,0xfc,0xff,0xff,0x0a,0x08,0x00,0x94,0xe5,0x00,0x00,0xa0,0xe3,
+ 0x00,0x00,0x52,0xe3,0x0b,0x00,0x00,0x9a,0x10,0x50,0x94,0xe5,0x02,0x00,0x15,0xe3,
+ 0xfc,0xff,0xff,0x0a,0x0c,0x30,0x84,0xe5,0x10,0x50,0x94,0xe5,0x01,0x00,0x15,0xe3,
+ 0xfc,0xff,0xff,0x0a,0x08,0x50,0x94,0xe5,0x01,0x50,0xc1,0xe4,0x01,0x00,0x80,0xe2,
+ 0x02,0x00,0x50,0xe1,0xf3,0xff,0xff,0x3a,0xc8,0x00,0xa0,0xe3,0x98,0xff,0xff,0xeb,
+ 0x70,0x40,0xbd,0xe8,0x1e,0xff,0x2f,0xe1,0x01,0x0c,0x00,0x02,0x01,0x02,0x00,0x02,
+ 0x00,0x01,0x00,0x02
+};
+
+struct atmel_private {
+ void *card; /* Bus dependent stucture varies for PCcard */
+ int (*present_callback)(void *); /* And callback which uses it */
+ char firmware_id[32];
+ unsigned char *firmware;
+ int firmware_length;
+ struct timer_list management_timer;
+ struct net_device *dev;
+ struct device *sys_dev;
+ struct iw_statistics wstats;
+ struct net_device_stats stats; // device stats
+ spinlock_t irqlock, timerlock; // spinlocks
+ enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
+ enum {
+ CARD_TYPE_PARALLEL_FLASH,
+ CARD_TYPE_SPI_FLASH,
+ CARD_TYPE_EEPROM
+ } card_type;
+ int is3com; /* is this a 3com card? they are uniquely borken */
+ int do_rx_crc; /* If we need to CRC incoming packets */
+ int probe_crc; /* set if we don't yet know */
+ int crc_ok_cnt, crc_ko_cnt; /* counters for probing */
+ u16 rx_desc_head;
+ u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
+ u16 tx_free_mem, tx_buff_head, tx_buff_tail;
+
+ u16 frag_seq, frag_len, frag_no;
+ u8 frag_source[6];
+
+ int wep_key_len[4]; /* need to know these and not stored in Mib. */
+ struct { /* NB this is matched to the hardware, don't change. */
+ u8 wep_is_on;
+ u8 default_key; /* 0..3 */
+ u8 reserved;
+ u8 exclude_unencrypted;
+
+ u32 WEPICV_error_count;
+ u32 WEP_excluded_count;
+
+ u8 wep_keys[4][13];
+ u8 encryption_level; /* 0, 1, 2 */
+ u8 reserved2[3];
+ } wep;
+
+ u16 host_info_base;
+ struct host_info_struct {
+ /* NB this is matched to the hardware, don't change. */
+ u8 volatile int_status;
+ u8 volatile int_mask;
+ u8 volatile lockout_host;
+ u8 volatile lockout_mac;
+
+ u16 tx_buff_pos;
+ u16 tx_buff_size;
+ u16 tx_desc_pos;
+ u16 tx_desc_count;
+
+ u16 rx_buff_pos;
+ u16 rx_buff_size;
+ u16 rx_desc_pos;
+ u16 rx_desc_count;
+
+ u16 build_version;
+ u16 command_pos;
+
+ u16 major_version;
+ u16 minor_version;
+
+ u16 func_ctrl;
+ u16 mac_status;
+ u16 generic_IRQ_type;
+ u8 reserved[2];
+ } host_info;
+
+ enum {
+ STATION_STATE_INITIALIZING,
+ STATION_STATE_SCANNING,
+ STATION_STATE_JOINNING,
+ STATION_STATE_AUTHENTICATING,
+ STATION_STATE_ASSOCIATING,
+ STATION_STATE_READY,
+ STATION_STATE_REASSOCIATING,
+ STATION_STATE_FORCED_JOINNING,
+ STATION_STATE_FORCED_JOIN_FAILURE,
+ STATION_STATE_DOWN,
+ STATION_STATE_NO_CARD,
+ STATION_STATE_MGMT_ERROR
+ } station_state;
+
+ int operating_mode, power_mode;
+ time_t last_qual;
+ int beacons_this_sec;
+ u64 last_beacon_timestamp;
+ int channel;
+ int reg_domain;
+ int tx_rate;
+ int auto_tx_rate;;
+ int rts_threshold;
+ int frag_threshold;
+ int long_retry, short_retry;
+ int preamble;
+ int default_beacon_period, beacon_period, listen_interval;
+ int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
+ int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
+ enum {
+ SITE_SURVEY_IDLE,
+ SITE_SURVEY_IN_PROGRESS,
+ SITE_SURVEY_COMPLETED
+ } site_survey_state;
+ time_t last_survey;
+
+ int station_was_associated, station_is_associated;
+ int fast_scan;
+
+ struct bss_info {
+ int channel;
+ int SSIDsize;
+ int RSSI;
+ int UsingWEP;
+ int preamble;
+ int beacon_period;
+ int BSStype;
+ u8 BSSID[6];
+ u8 SSID[MAX_SSID_LENGTH];
+ } BSSinfo[MAX_BSS_ENTRIES];
+ int BSS_list_entries, current_BSS;
+ int connect_to_any_BSS;
+ int SSID_size, new_SSID_size;
+ u8 CurrentBSSID[6], BSSID[6];
+ u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
+ u8 rx_buf[MAX_WIRELESS_BODY];
+
+};
+
+static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
+
+static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len);
+static void atmel_set_gcr(struct net_device *dev, u16 mask);
+static void atmel_clear_gcr(struct net_device *dev, u16 mask);
+static int atmel_lock_mac(struct atmel_private *priv);
+static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
+static void atmel_command_irq(struct atmel_private *priv);
+static int atmel_validate_channel(struct atmel_private *priv, int channel);
+static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u16 frame_len, u8 rssi);
+static void atmel_management_timer(u_long a);
+static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
+static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u8 *body, int body_len);
+
+static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data);
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data);
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_scan(struct atmel_private *priv, int specific_ssid);
+static void atmel_join_bss(struct atmel_private *priv, int bss_index);
+static void atmel_smooth_qual(struct atmel_private *priv);
+static void atmel_writeAR(struct net_device *dev, u16 data);
+static int probe_atmel_card(struct net_device *dev);
+int reset_atmel_card(struct net_device *dev );
+static void atmel_enter_state(struct atmel_private *priv, int new_state);
+
+static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
+{
+ return priv->host_info_base + offset;
+}
+
+static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
+{
+ return priv->host_info.command_pos + offset;
+}
+
+static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
+{
+ return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
+}
+
+static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
+{
+ return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
+}
+
+static inline u8 atmel_read8(struct net_device *dev, u16 offset)
+{
+ return inb(dev->base_addr + offset);
+}
+
+static inline void atmel_write8(struct net_device *dev, u16 offset, u8 data)
+{
+ outb(data, dev->base_addr + offset);
+}
+
+static inline u16 atmel_read16(struct net_device *dev, u16 offset)
+{
+ return inw(dev->base_addr + offset);
+}
+
+static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
+{
+ outw(data, dev->base_addr + offset);
+}
+
+
+static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
+{
+ atmel_writeAR(priv->dev, pos);
+ return atmel_read8(priv->dev, DR);
+}
+
+static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
+{
+ atmel_writeAR(priv->dev, pos);
+ atmel_write8(priv->dev, DR, data);
+}
+
+static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
+{
+ atmel_writeAR(priv->dev, pos);
+ return atmel_read16(priv->dev, DR);
+}
+
+static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
+{
+ atmel_writeAR(priv->dev, pos);
+ atmel_write16(priv->dev, DR, data);
+}
+
+static const struct iw_handler_def atmel_handler_def;
+
+static void tx_done_irq(struct atmel_private *priv)
+{
+ int i;
+
+ for (i = 0;
+ atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
+ i < priv->host_info.tx_desc_count;
+ i++) {
+
+ u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
+ u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
+ u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
+
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head), 0);
+
+ priv->tx_free_mem += msdu_size;
+ priv->tx_desc_free++;
+
+ if (priv->tx_buff_head + msdu_size > (priv->host_info.tx_buff_pos + priv->host_info.tx_buff_size))
+ priv->tx_buff_head = 0;
+ else
+ priv->tx_buff_head += msdu_size;
+
+ if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
+ priv->tx_desc_head++ ;
+ else
+ priv->tx_desc_head = 0;
+
+ if (type == TX_PACKET_TYPE_DATA) {
+ if (status == TX_STATUS_SUCCESS)
+ priv->stats.tx_packets++;
+ else
+ priv->stats.tx_errors++;
+ netif_wake_queue(priv->dev);
+ }
+ }
+}
+
+static u16 find_tx_buff(struct atmel_private *priv, u16 len)
+{
+ u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
+
+ if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
+ return 0;
+
+ if (bottom_free >= len)
+ return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
+
+ if (priv->tx_free_mem - bottom_free >= len) {
+ priv->tx_buff_tail = 0;
+ return priv->host_info.tx_buff_pos;
+ }
+
+ return 0;
+}
+
+static void tx_update_descriptor(struct atmel_private *priv, u16 len, u16 buff, u8 type)
+{
+ atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
+ atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
+ atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type);
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate);
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0);
+ atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L);
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN);
+ if (priv->tx_desc_previous != priv->tx_desc_tail)
+ atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
+ priv->tx_desc_previous = priv->tx_desc_tail;
+ if (priv->tx_desc_tail < (priv->host_info.tx_desc_count -1 ))
+ priv->tx_desc_tail++;
+ else
+ priv->tx_desc_tail = 0;
+ priv->tx_desc_free--;
+ priv->tx_free_mem -= len;
+
+}
+
+static int start_tx (struct sk_buff *skb, struct net_device *dev)
+{
+ struct atmel_private *priv = (struct atmel_private *)dev->priv;
+ struct ieee802_11_hdr header;
+ unsigned long flags;
+ u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+
+ if(priv->station_state != STATION_STATE_READY) {
+ priv->stats.tx_errors++;
+ return 0;
+ }
+
+ if (priv->card && priv->present_callback &&
+ !(*priv->present_callback)(priv->card)) {
+ priv->stats.tx_errors++;
+ return 0;
+ }
+
+ /* first ensure the timer func cannot run */
+ spin_lock_bh(&priv->timerlock);
+ /* then stop the hardware ISR */
+ spin_lock_irqsave(&priv->irqlock, flags);
+ /* nb doing the above in the opposite order will deadlock */
+
+ /* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
+ 12 first bytes (containing DA/SA) and put them in the appropriate fields of
+ the Wireless Header. Thus the packet length is then the initial + 18 (+30-12) */
+
+ if (!(buff = find_tx_buff(priv, len + 18))) {
+ priv->stats.tx_dropped++;
+ spin_unlock_irqrestore(&priv->irqlock, flags);
+ spin_unlock_bh(&priv->timerlock);
+ netif_stop_queue(dev);
+ return 1;
+ }
+
+ frame_ctl = IEEE802_11_FTYPE_DATA;
+ header.duration_id = 0;
+ header.seq_ctl = 0;
+ if (priv->wep.wep_is_on)
+ frame_ctl |= IEEE802_11_FCTL_WEP;
+ if (priv->operating_mode == IW_MODE_ADHOC) {
+ memcpy(&header.addr1, skb->data, 6);
+ memcpy(&header.addr2, dev->dev_addr, 6);
+ memcpy(&header.addr3, priv->BSSID, 6);
+ } else {
+ frame_ctl |= IEEE802_11_FCTL_TODS;
+ memcpy(&header.addr1, priv->CurrentBSSID, 6);
+ memcpy(&header.addr2, dev->dev_addr, 6);
+ memcpy(&header.addr3, skb->data, 6);
+ }
+
+ header.frame_ctl = cpu_to_le16(frame_ctl);
+ /* Copy the wireless header into the card */
+ atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
+ /* Copy the packet sans its 802.3 header addresses which have been replaced */
+ atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
+ priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
+
+ tx_update_descriptor(priv, len + 18, buff, TX_PACKET_TYPE_DATA);
+ dev->trans_start = jiffies;
+ priv->stats.tx_bytes += len;
+
+ spin_unlock_irqrestore(&priv->irqlock, flags);
+ spin_unlock_bh(&priv->timerlock);
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+static void atmel_transmit_management_frame(struct atmel_private *priv,
+ struct ieee802_11_hdr *header,
+ u8 *body, int body_len)
+{
+ u16 buff;
+ int len = MGMT_FRAME_BODY_OFFSET + body_len;
+
+ if (!(buff = find_tx_buff(priv, len)))
+ return;
+
+ atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
+ atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);
+ priv->tx_buff_tail += len;
+ tx_update_descriptor(priv, len, buff, TX_PACKET_TYPE_MGMT);
+}
+
+static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u16 msdu_size, u16 rx_packet_loc, u32 crc)
+{
+ /* fast path: unfragmented packet copy directly into skbuf */
+ u8 mac4[6];
+ struct sk_buff *skb;
+ unsigned char *skbp;
+
+ /* get the final, mac 4 header field, this tells us encapsulation */
+ atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
+ msdu_size -= 6;
+
+ if (priv->do_rx_crc) {
+ crc = crc32_le(crc, mac4, 6);
+ msdu_size -= 4;
+ }
+
+ if (!(skb = dev_alloc_skb(msdu_size + 14))) {
+ priv->stats.rx_dropped++;
+ return;
+ }
+
+ skb_reserve(skb, 2);
+ skbp = skb_put(skb, msdu_size + 12);
+ atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
+
+ if (priv->do_rx_crc) {
+ u32 netcrc;
+ crc = crc32_le(crc, skbp + 12, msdu_size);
+ atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
+ if ((crc ^ 0xffffffff) != netcrc) {
+ priv->stats.rx_crc_errors++;
+ dev_kfree_skb(skb);
+ return;
+ }
+ }
+
+ memcpy(skbp, header->addr1, 6); /* destination address */
+ if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ memcpy(&skbp[6], header->addr3, 6);
+ else
+ memcpy(&skbp[6], header->addr2, 6); /* source address */
+
+ priv->dev->last_rx=jiffies;
+ skb->dev = priv->dev;
+ skb->protocol = eth_type_trans(skb, priv->dev);
+ skb->ip_summed = CHECKSUM_NONE;
+ netif_rx(skb);
+ priv->stats.rx_bytes += 12 + msdu_size;
+ priv->stats.rx_packets++;
+}
+
+/* Test to see if the packet in card memory at packet_loc has a valid CRC
+ It doesn't matter that this is slow: it is only used to proble the first few packets. */
+static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
+{
+ int i = msdu_size - 4;
+ u32 netcrc, crc = 0xffffffff;
+
+ if (msdu_size < 4)
+ return 0;
+
+ atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
+
+ atmel_writeAR(priv->dev, packet_loc);
+ while (i--) {
+ u8 octet = atmel_read8(priv->dev, DR);
+ crc = crc32_le(crc, &octet, 1);
+ }
+
+ return (crc ^ 0xffffffff) == netcrc;
+}
+
+static void frag_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
+{
+ u8 mac4[6];
+ u8 source[6];
+ struct sk_buff *skb;
+
+ if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ memcpy(source, header->addr3, 6);
+ else
+ memcpy(source, header->addr2, 6);
+
+ rx_packet_loc += 24; /* skip header */
+
+ if (priv->do_rx_crc)
+ msdu_size -= 4;
+
+ if (frag_no == 0) { /* first fragment */
+ atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6);
+ msdu_size -= 6;
+ rx_packet_loc += 6;
+
+ if (priv->do_rx_crc)
+ crc = crc32_le(crc, mac4, 6);
+
+ priv->frag_seq = seq_no;
+ priv->frag_no = 1;
+ priv->frag_len = msdu_size;
+ memcpy(priv->frag_source, source, 6);
+ memcpy(&priv->rx_buf[6], source, 6);
+ memcpy(priv->rx_buf, header->addr1, 6);
+
+ atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
+
+ if (priv->do_rx_crc) {
+ u32 netcrc;
+ crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
+ atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
+ if ((crc ^ 0xffffffff) != netcrc) {
+ priv->stats.rx_crc_errors++;
+ memset(priv->frag_source, 0xff, 6);
+ }
+ }
+
+ } else if (priv->frag_no == frag_no &&
+ priv->frag_seq == seq_no &&
+ memcmp(priv->frag_source, source, 6) == 0) {
+
+ atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
+ rx_packet_loc, msdu_size);
+ if (priv->do_rx_crc) {
+ u32 netcrc;
+ crc = crc32_le(crc,
+ &priv->rx_buf[12 + priv->frag_len],
+ msdu_size);
+ atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
+ if ((crc ^ 0xffffffff) != netcrc) {
+ priv->stats.rx_crc_errors++;
+ memset(priv->frag_source, 0xff, 6);
+ more_frags = 1; /* don't send broken assembly */
+ }
+ }
+
+ priv->frag_len += msdu_size;
+ priv->frag_no++;
+
+ if (!more_frags) { /* last one */
+ memset(priv->frag_source, 0xff, 6);
+ if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
+ priv->stats.rx_dropped++;
+ } else {
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, priv->frag_len + 12),
+ priv->rx_buf,
+ priv->frag_len + 12);
+ priv->dev->last_rx = jiffies;
+ skb->dev = priv->dev;
+ skb->protocol = eth_type_trans(skb, priv->dev);
+ skb->ip_summed = CHECKSUM_NONE;
+ netif_rx(skb);
+ priv->stats.rx_bytes += priv->frag_len + 12;
+ priv->stats.rx_packets++;
+ }
+ }
+
+ } else
+ priv->wstats.discard.fragment++;
+}
+
+static void rx_done_irq(struct atmel_private *priv)
+{
+ int i;
+ struct ieee802_11_hdr header;
+
+ for (i = 0;
+ atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
+ i < priv->host_info.rx_desc_count;
+ i++) {
+
+ u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
+ u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
+ u32 crc = 0xffffffff;
+
+ if (status != RX_STATUS_SUCCESS) {
+ if (status == 0xc1) /* determined by experiment */
+ priv->wstats.discard.nwid++;
+ else
+ priv->stats.rx_errors++;
+ goto next;
+ }
+
+ msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
+ rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
+
+ if (msdu_size < 30) {
+ priv->stats.rx_errors++;
+ goto next;
+ }
+
+ /* Get header as far as end of seq_ctl */
+ atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
+ frame_ctl = le16_to_cpu(header.frame_ctl);
+ seq_control = le16_to_cpu(header.seq_ctl);
+
+ /* probe for CRC use here if needed once five packets have arrived with
+ the same crc status, we assume we know what's happening and stop probing */
+ if (priv->probe_crc) {
+ if (!priv->wep.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
+ priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
+ } else {
+ priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
+ }
+ if (priv->do_rx_crc) {
+ if (priv->crc_ok_cnt++ > 5)
+ priv->probe_crc = 0;
+ } else {
+ if (priv->crc_ko_cnt++ > 5)
+ priv->probe_crc = 0;
+ }
+ }
+
+ /* don't CRC header when WEP in use */
+ if (priv->do_rx_crc && (!priv->wep.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
+ crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
+ }
+ msdu_size -= 24; /* header */
+
+ if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_DATA) {
+
+ int more_fragments = frame_ctl & IEEE802_11_FCTL_MOREFRAGS;
+ u8 packet_fragment_no = seq_control & IEEE802_11_SCTL_FRAG;
+ u16 packet_sequence_no = (seq_control & IEEE802_11_SCTL_SEQ) >> 4;
+
+ if (!more_fragments && packet_fragment_no == 0 ) {
+ fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
+ } else {
+ frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
+ packet_sequence_no, packet_fragment_no, more_fragments);
+ }
+ }
+
+ if ((frame_ctl & IEEE802_11_FCTL_FTYPE) == IEEE802_11_FTYPE_MGMT) {
+ /* copy rest of packet into buffer */
+ atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
+
+ /* we use the same buffer for frag reassembly and control packets */
+ memset(priv->frag_source, 0xff, 6);
+
+ if (priv->do_rx_crc) {
+ /* last 4 octets is crc */
+ msdu_size -= 4;
+ crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
+ if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
+ priv->stats.rx_crc_errors++;
+ goto next;
+ }
+ }
+
+ atmel_management_frame(priv, &header, msdu_size,
+ atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
+ }
+
+ next:
+ /* release descriptor */
+ atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
+
+ if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
+ priv->rx_desc_head++;
+ else
+ priv->rx_desc_head = 0;
+ }
+}
+
+static void reset_irq_status(struct atmel_private *priv, u8 mask)
+{
+ u8 isr;
+
+ atmel_lock_mac(priv);
+ isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
+ isr ^= mask;
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+}
+
+static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct atmel_private *priv = (struct atmel_private *) dev->priv;
+ u8 isr;
+
+ if (priv->card && priv->present_callback &&
+ !(*priv->present_callback)(priv->card))
+ return IRQ_HANDLED;
+
+ atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+
+ while (1) {
+ if (!atmel_lock_mac(priv)) {
+ printk(KERN_ALERT "%s: MAC gone away in ISR.\n", dev->name);
+ /* bad things - don't re-enable interrupts */
+ return IRQ_HANDLED;
+ }
+
+ isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+ if (isr)
+ atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
+ else
+ break; /* no pending irqs */
+
+ if (isr & ISR_OUT_OF_RANGE) {
+ reset_irq_status(priv, ISR_OUT_OF_RANGE);
+ if(priv->operating_mode == IW_MODE_INFRA &&
+ priv->station_state == STATION_STATE_READY) {
+ priv->station_is_associated = 0;
+ atmel_scan(priv, 1);
+ }
+ } else if (isr & ISR_RxCOMPLETE) {
+ reset_irq_status(priv, ISR_RxCOMPLETE);
+ rx_done_irq(priv);
+ } else if (isr & ISR_TxCOMPLETE) {
+ reset_irq_status(priv, ISR_TxCOMPLETE);
+ tx_done_irq(priv);
+ } else if (isr & ISR_RxFRAMELOST) {
+ reset_irq_status(priv, ISR_RxFRAMELOST);
+ priv->wstats.discard.misc++;
+ rx_done_irq(priv);
+ } else if (isr & ISR_FATAL_ERROR) {
+ reset_irq_status(priv, ISR_FATAL_ERROR);
+ printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ } else if (isr & ISR_COMMAND_COMPLETE) {
+ reset_irq_status(priv, ISR_COMMAND_COMPLETE);
+ atmel_command_irq(priv);
+ } else if (isr & ISR_IBSS_MERGE) {
+ reset_irq_status(priv, ISR_IBSS_MERGE);
+ atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
+ priv->CurrentBSSID, 6);
+ } else if (isr & ISR_GENERIC_IRQ) {
+ reset_irq_status(priv, ISR_GENERIC_IRQ);
+ printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);
+ }
+ }
+
+ atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+ return IRQ_HANDLED;
+}
+
+
+static struct net_device_stats *atmel_get_stats (struct net_device *dev)
+{
+ struct atmel_private *priv = (struct atmel_private *)dev->priv;
+ return &priv->stats;
+}
+
+static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
+{
+ struct atmel_private *priv = (struct atmel_private *)dev->priv;
+
+ /* update the link quality here in case we are seeing no beacons
+ at all to drive the process */
+ atmel_smooth_qual(priv);
+
+ priv->wstats.status = priv->station_state;
+
+ if (priv->operating_mode == IW_MODE_INFRA) {
+ if (priv->station_state != STATION_STATE_READY) {
+ priv->wstats.qual.qual = 0;
+ priv->wstats.qual.level = 0;
+ }
+ priv->wstats.qual.noise = 0;
+ priv->wstats.qual.updated = 7;
+ } else {
+ // Quality levels cannot be determined in ad-hoc mode,
+ // because we can 'hear' more that one remote station.
+ priv->wstats.qual.qual = 0;
+ priv->wstats.qual.level = 0;
+ priv->wstats.qual.noise = 0;
+ priv->wstats.qual.updated = 0;
+ priv->wstats.miss.beacon = 0;
+ }
+
+ return (&priv->wstats);
+}
+
+static int atmel_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > 2312))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static int atmel_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
+ reset_atmel_card(dev);
+ return 0;
+}
+
+static int atmel_open (struct net_device *dev)
+{
+ struct atmel_private *priv = (struct atmel_private *) dev->priv;
+ priv->station_state = STATION_STATE_INITIALIZING;
+ if (!reset_atmel_card(dev)) {
+ priv->station_state = STATION_STATE_DOWN;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int atmel_close (struct net_device *dev)
+{
+ struct atmel_private *priv = (struct atmel_private *) dev->priv;
+
+ if (netif_running(dev))
+ netif_stop_queue(dev);
+
+ priv->station_state = STATION_STATE_DOWN;
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(dev, GCR, 0x0060);
+ atmel_write16(dev, GCR, 0x0040);
+ return 0;
+}
+
+static int atmel_proc_output (char *buf, struct atmel_private *priv)
+{
+ char *p = buf;
+ char *s, *r, *c;
+
+ p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
+
+ if (priv->station_state != STATION_STATE_DOWN) {
+ p += sprintf(p, "Firmware version:\t%d.%d build %d ",
+ priv->host_info.major_version,
+ priv->host_info.minor_version,
+ priv->host_info.build_version);
+
+ if (priv->card_type != CARD_TYPE_EEPROM)
+ p += sprintf(p, "[built-in]\n");
+ else if (priv->firmware)
+ p += sprintf(p, "[%s loaded by host]\n", priv->firmware_id);
+ else
+ p += sprintf(p, "[%s loaded by hotplug]\n", priv->firmware_id);
+
+ switch(priv->card_type) {
+ case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
+ case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;
+ case CARD_TYPE_EEPROM: c = "EEPROM"; break;
+ default: c = "";
+ }
+
+ switch (priv->reg_domain) {
+ case REG_DOMAIN_FCC: r = "USA"; break;
+ case REG_DOMAIN_DOC: r = "Canada"; break;
+ case REG_DOMAIN_ETSI: r = "Europe"; break;
+ case REG_DOMAIN_SPAIN: r = "Spain"; break;
+ case REG_DOMAIN_FRANCE: r = "France"; break;
+ case REG_DOMAIN_MKK: r = "Japan (MKK)"; break;
+ case REG_DOMAIN_MKK1: r = "Japan (MKK1)"; break;
+ case REG_DOMAIN_ISRAEL: r = "Israel"; break;
+ default: r = "";
+ }
+ p += sprintf(p, "MAC memory type:\t%s\n", c);
+ p += sprintf(p, "Regulatory domain:\t%s\n", r);
+ p += sprintf(p, "Host CRC checking:\t%s\n",
+ priv->do_rx_crc ? "On" : "Off");
+ }
+
+ switch(priv->station_state) {
+ case STATION_STATE_INITIALIZING: s = "Initialising"; break;
+ case STATION_STATE_SCANNING: s = "Scanning"; break;
+ case STATION_STATE_JOINNING: s = "Joining"; break;
+ case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break;
+ case STATION_STATE_ASSOCIATING: s = "Associating"; break;
+ case STATION_STATE_READY: s = "Ready"; break;
+ case STATION_STATE_REASSOCIATING: s = "Reassociating"; break;
+ case STATION_STATE_FORCED_JOINNING: s = "Forced joining"; break;
+ case STATION_STATE_FORCED_JOIN_FAILURE: s = "Forced join failure"; break;
+ case STATION_STATE_NO_CARD: s = "No card"; break;
+ case STATION_STATE_MGMT_ERROR: s = "Management error"; break;
+ case STATION_STATE_DOWN: s = "Down"; break;
+ default: s = "";
+ }
+
+ p += sprintf(p, "Current state:\t\t%s\n", s);
+ return p - buf;
+}
+
+static int atmel_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ struct atmel_private *priv = (struct atmel_private *)data;
+ int len = atmel_proc_output (page, priv);
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+
+struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware_id, int is3com,
+ struct device *sys_dev, int (*card_present)(void *), void *card)
+{
+ struct net_device *dev;
+ struct atmel_private *priv;
+ int rc;
+
+ /* Create the network device object. */
+ dev = alloc_etherdev(sizeof(*priv));
+ if (!dev) {
+ printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
+ return NULL;
+ }
+ if (dev_alloc_name(dev, dev->name) < 0) {
+ printk(KERN_ERR "atmel: Couldn't get name!\n");
+ goto err_out_free;
+ }
+
+ priv = dev->priv;
+ priv->dev = dev;
+ priv->sys_dev = sys_dev;
+ priv->present_callback = card_present;
+ priv->card = card;
+ priv->firmware = NULL;
+ if (firmware) /* module parameter */
+ strcpy(priv->firmware_id, firmware);
+ else if (firmware_id) /* from PCMCIA card-matching or PCI */
+ strcpy(priv->firmware_id, firmware_id);
+ else
+ priv->firmware_id[0] = '\0';
+ priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
+ priv->station_state = STATION_STATE_DOWN;
+ priv->is3com = is3com;
+ priv->do_rx_crc = 0;
+ /* For PCMCIA cards, some chips need CRC, some don't
+ so we have to probe. */
+ if (priv->bus_type == BUS_TYPE_PCCARD) {
+ priv->probe_crc = 1;
+ priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
+ } else
+ priv->probe_crc = 0;
+ memset(&priv->stats, 0, sizeof(priv->stats));
+ memset(&priv->wstats, 0, sizeof(priv->wstats));
+ priv->last_qual = jiffies;
+ priv->last_beacon_timestamp = 0;
+ memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
+ memset(priv->BSSID, 0, 6);
+ priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
+ priv->station_was_associated = 0;
+
+ priv->last_survey = jiffies;
+ priv->preamble = LONG_PREAMBLE;
+ priv->operating_mode = IW_MODE_INFRA;
+ priv->connect_to_any_BSS = 0;
+ priv->tx_rate = 3;
+ priv->auto_tx_rate = 1;
+ priv->channel = 4;
+ priv->power_mode = 0;
+ priv->SSID[0] = '\0';
+ priv->SSID_size = 0;
+ priv->new_SSID_size = 0;
+ priv->frag_threshold = 2346;
+ priv->rts_threshold = 2347;
+ priv->short_retry = 7;
+ priv->long_retry = 4;
+ priv->wep.wep_is_on = 0;
+ priv->wep.default_key = 0;
+ priv->wep.encryption_level = 0;
+ priv->default_beacon_period = priv->beacon_period = 100;
+ priv->listen_interval = 1;
+
+ init_timer(&priv->management_timer);
+ spin_lock_init(&priv->irqlock);
+ spin_lock_init(&priv->timerlock);
+ priv->management_timer.function = atmel_management_timer;
+ priv->management_timer.data = (unsigned long) dev;
+
+ dev->open = atmel_open;
+ dev->stop = atmel_close;
+ dev->change_mtu = atmel_change_mtu;
+ dev->set_mac_address = atmel_set_mac_address;
+ dev->hard_start_xmit = start_tx;
+ dev->get_stats = atmel_get_stats;
+ dev->get_wireless_stats = atmel_get_wireless_stats;
+ dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def;
+ dev->do_ioctl = atmel_ioctl;
+ dev->irq = irq;
+ dev->base_addr = port;
+
+ if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
+ printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
+ goto err_out_free;
+ }
+
+ if (priv->bus_type == BUS_TYPE_PCI &&
+ !request_region( dev->base_addr, 64, dev->name )) {
+ goto err_out_irq;
+ }
+
+ if (register_netdev(dev))
+ goto err_out_res;
+
+ if (!probe_atmel_card(dev))
+ goto err_out_res;
+
+ create_proc_read_entry ("driver/atmel", 0, 0, atmel_read_proc, priv);
+
+ printk(KERN_INFO "%s: Atmel at76c50x wireless. Version %d.%d simon@thekelleys.org.uk\n",
+ dev->name, DRIVER_MAJOR, DRIVER_MINOR);
+
+ SET_MODULE_OWNER(dev);
+ return dev;
+
+ err_out_res:
+ if (priv->bus_type == BUS_TYPE_PCI)
+ release_region( dev->base_addr, 64 );
+ err_out_irq:
+ free_irq(dev->irq, dev);
+ err_out_free:
+ kfree(dev);
+ return NULL;
+}
+
+EXPORT_SYMBOL(init_atmel_card);
+
+void stop_atmel_card(struct net_device *dev, int freeres)
+{
+ struct atmel_private *priv = dev->priv;
+ unregister_netdev(dev);
+
+ /* put a brick on it... */
+
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(dev, GCR, 0x0060);
+ atmel_write16(dev, GCR, 0x0040);
+
+ remove_proc_entry("driver/atmel", NULL);
+ del_timer_sync(&priv->management_timer);
+ free_irq(dev->irq, dev);
+ if (priv->firmware)
+ kfree(priv->firmware);
+ if (freeres) {
+ /* PCMCIA frees this stuff, so only for PCI */
+ release_region(dev->base_addr, 64);
+ }
+ kfree(dev);
+}
+
+EXPORT_SYMBOL(stop_atmel_card);
+
+static const struct {
+ int reg_domain;
+ int min, max;
+} channel_table[] = { { REG_DOMAIN_FCC, 1, 11},
+ { REG_DOMAIN_DOC, 1, 11},
+ { REG_DOMAIN_ETSI, 1, 13},
+ { REG_DOMAIN_SPAIN, 10, 11},
+ { REG_DOMAIN_FRANCE, 10, 13},
+ { REG_DOMAIN_MKK, 14, 14},
+ { REG_DOMAIN_MKK1, 1, 14},
+ { REG_DOMAIN_ISRAEL, 9} };
+
+
+static int atmel_validate_channel(struct atmel_private *priv, int channel)
+{
+ /* check that channel is OK, if so return zero,
+ else return suitable default channel */
+ int i;
+
+ for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
+ if (priv->reg_domain == channel_table[i].reg_domain) {
+ if (channel >= channel_table[i].min &&
+ channel <= channel_table[i].max)
+ return 0;
+ else
+ return channel_table[i].min;
+ }
+ return 1;
+}
+
+static int atmel_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ /* Check if we asked for `any' */
+ if(dwrq->flags == 0) {
+ priv->connect_to_any_BSS = 1;
+ } else {
+ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ priv->connect_to_any_BSS = 0;
+
+ /* Check the size of the string */
+ if (dwrq->length > MAX_SSID_LENGTH + 1)
+ return -E2BIG ;
+ if (index != 0)
+ return -EINVAL;
+
+ memcpy(priv->new_SSID, extra, dwrq->length - 1);
+ priv->new_SSID_size = dwrq->length - 1;
+ }
+
+ return -EINPROGRESS;
+}
+
+static int atmel_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ /* Get the current SSID */
+ if (priv->SSID_size == 0) {
+ memcpy(extra, priv->new_SSID, priv->new_SSID_size);
+ extra[priv->new_SSID_size] = '\0';
+ dwrq->length = priv->new_SSID_size + 1;
+ } else {
+ memcpy(extra, priv->SSID, priv->SSID_size);
+ extra[priv->SSID_size] = '\0';
+ dwrq->length = priv->SSID_size + 1;
+ }
+
+ dwrq->flags = !priv->connect_to_any_BSS; /* active */
+
+ return 0;
+}
+
+static int atmel_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ memcpy(awrq->sa_data, priv->CurrentBSSID, 6);
+ awrq->sa_family = ARPHRD_ETHER;
+
+ return 0;
+}
+
+static int atmel_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ /* Basic checking: do we have a key to set ?
+ * Note : with the new API, it's impossible to get a NULL pointer.
+ * Therefore, we need to check a key size == 0 instead.
+ * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
+ * when no key is present (only change flags), but older versions
+ * don't do it. - Jean II */
+ if (dwrq->length > 0) {
+ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+ int current_index = priv->wep.default_key;
+ /* Check the size of the key */
+ if (dwrq->length > 13) {
+ return -EINVAL;
+ }
+ /* Check the index (none -> use current) */
+ if (index < 0 || index >= 4)
+ index = current_index;
+ else
+ priv->wep.default_key = index;
+ /* Set the length */
+ if (dwrq->length > 5)
+ priv->wep_key_len[index] = 13;
+ else
+ if (dwrq->length > 0)
+ priv->wep_key_len[index] = 5;
+ else
+ /* Disable the key */
+ priv->wep_key_len[index] = 0;
+ /* Check if the key is not marked as invalid */
+ if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
+ /* Cleanup */
+ memset(priv->wep.wep_keys[index], 0, 13);
+ /* Copy the key in the driver */
+ memcpy(priv->wep.wep_keys[index], extra, dwrq->length);
+ }
+ /* WE specify that if a valid key is set, encryption
+ * should be enabled (user may turn it off later)
+ * This is also how "iwconfig ethX key on" works */
+ if (index == current_index &&
+ priv->wep_key_len[index] > 0) {
+ priv->wep.wep_is_on = 1;
+ priv->wep.exclude_unencrypted = 1;
+ if (priv->wep_key_len[index] > 5)
+ priv->wep.encryption_level = 2;
+ else
+ priv->wep.encryption_level = 1;
+ }
+ } else {
+ /* Do we want to just set the transmit key index ? */
+ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+ if ( index>=0 && index < 4 ) {
+ priv->wep.default_key = index;
+ } else
+ /* Don't complain if only change the mode */
+ if(!dwrq->flags & IW_ENCODE_MODE) {
+ return -EINVAL;
+ }
+ }
+ /* Read the flags */
+ if(dwrq->flags & IW_ENCODE_DISABLED) {
+ priv->wep.wep_is_on = 0;
+ priv->wep.encryption_level = 0;
+ } else {
+ priv->wep.wep_is_on = 1;
+ if (priv->wep_key_len[priv->wep.default_key] > 5)
+ priv->wep.encryption_level = 2;
+ else
+ priv->wep.encryption_level = 1;
+ }
+ if(dwrq->flags & IW_ENCODE_RESTRICTED)
+ priv->wep.exclude_unencrypted = 1;
+ if(dwrq->flags & IW_ENCODE_OPEN)
+ priv->wep.exclude_unencrypted = 0;
+
+ return -EINPROGRESS; /* Call commit handler */
+}
+
+
+static int atmel_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+ if (!priv->wep.wep_is_on)
+ dwrq->flags = IW_ENCODE_DISABLED;
+ else if (priv->wep.exclude_unencrypted)
+ dwrq->flags = IW_ENCODE_RESTRICTED;
+ else
+ dwrq->flags = IW_ENCODE_OPEN;
+
+ /* Which key do we want ? -1 -> tx index */
+ if (index < 0 || index >= 4)
+ index = priv->wep.default_key;
+ dwrq->flags |= index + 1;
+ /* Copy the key to the user buffer */
+ dwrq->length = priv->wep_key_len[index];
+ if (dwrq->length > 16) {
+ dwrq->length=0;
+ } else {
+ memset(extra, 0, 16);
+ memcpy(extra, priv->wep.wep_keys[index], dwrq->length);
+ }
+
+ return 0;
+}
+
+static int atmel_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ char *cwrq,
+ char *extra)
+{
+ strcpy(cwrq, "IEEE 802.11-DS");
+ return 0;
+}
+
+static int atmel_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ if (vwrq->fixed == 0) {
+ priv->tx_rate = 3;
+ priv->auto_tx_rate = 1;
+ } else {
+ priv->auto_tx_rate = 0;
+
+ /* Which type of value ? */
+ if((vwrq->value < 4) && (vwrq->value >= 0)) {
+ /* Setting by rate index */
+ priv->tx_rate = vwrq->value;
+ } else {
+ /* Setting by frequency value */
+ switch (vwrq->value) {
+ case (int)1e6: priv->tx_rate = 0; break;
+ case (int)2e6: priv->tx_rate = 1; break;
+ case (int)5.5e6: priv->tx_rate = 2; break;
+ case (int)11e6: priv->tx_rate = 3; break;
+ default: return -EINVAL;
+ }
+ }
+ }
+
+ return -EINPROGRESS;
+}
+
+static int atmel_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ if (*uwrq != IW_MODE_ADHOC && *uwrq != IW_MODE_INFRA)
+ return -EINVAL;
+
+ priv->operating_mode = *uwrq;
+ return -EINPROGRESS;
+}
+
+static int atmel_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *uwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ *uwrq = priv->operating_mode;
+ return 0;
+}
+
+static int atmel_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ if (priv->auto_tx_rate) {
+ vwrq->fixed = 0;
+ vwrq->value = 11e6;
+ } else {
+ vwrq->fixed = 1;
+ switch(priv->tx_rate) {
+ case 0: vwrq->value = 1e6; break;
+ case 1: vwrq->value = 2e6; break;
+ case 2: vwrq->value = 5.5e6; break;
+ case 3: vwrq->value = 11e6; break;
+ }
+ }
+ return 0;
+}
+
+static int atmel_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ priv->power_mode = vwrq->disabled ? 0 : 1;
+ return -EINPROGRESS;
+}
+
+static int atmel_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ vwrq->disabled = priv->power_mode ? 0 : 1;
+ vwrq->flags = IW_POWER_ON;
+ return 0;
+}
+
+static int atmel_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ if(!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
+ if(vwrq->flags & IW_RETRY_MAX)
+ priv->long_retry = vwrq->value;
+ else if (vwrq->flags & IW_RETRY_MIN)
+ priv->short_retry = vwrq->value;
+ else {
+ /* No modifier : set both */
+ priv->long_retry = vwrq->value;
+ priv->short_retry = vwrq->value;
+ }
+ return -EINPROGRESS;
+ }
+
+ return -EINVAL;
+}
+
+static int atmel_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ vwrq->disabled = 0; /* Can't be disabled */
+
+ /* Note : by default, display the min retry number */
+ if((vwrq->flags & IW_RETRY_MAX)) {
+ vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ vwrq->value = priv->long_retry;
+ } else {
+ vwrq->flags = IW_RETRY_LIMIT;
+ vwrq->value = priv->short_retry;
+ if(priv->long_retry != priv->short_retry)
+ vwrq->flags |= IW_RETRY_MIN;
+ }
+
+ return 0;
+}
+
+static int atmel_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int rthr = vwrq->value;
+
+ if(vwrq->disabled)
+ rthr = 2347;
+ if((rthr < 0) || (rthr > 2347)) {
+ return -EINVAL;
+ }
+ priv->rts_threshold = rthr;
+
+ return -EINPROGRESS; /* Call commit handler */
+}
+
+static int atmel_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ vwrq->value = priv->rts_threshold;
+ vwrq->disabled = (vwrq->value >= 2347);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+static int atmel_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int fthr = vwrq->value;
+
+ if(vwrq->disabled)
+ fthr = 2346;
+ if((fthr < 256) || (fthr > 2346)) {
+ return -EINVAL;
+ }
+ fthr &= ~0x1; /* Get an even value - is it really needed ??? */
+ priv->frag_threshold = fthr;
+
+ return -EINPROGRESS; /* Call commit handler */
+}
+
+static int atmel_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ vwrq->value = priv->frag_threshold;
+ vwrq->disabled = (vwrq->value >= 2346);
+ vwrq->fixed = 1;
+
+ return 0;
+}
+
+const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
+ 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
+
+static int atmel_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int rc = -EINPROGRESS; /* Call commit handler */
+
+ /* If setting by frequency, convert to a channel */
+ if((fwrq->e == 1) &&
+ (fwrq->m >= (int) 2.412e8) &&
+ (fwrq->m <= (int) 2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+ while((c < 14) && (f != frequency_list[c]))
+ c++;
+ /* Hack to fall through... */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ /* Setting by channel number */
+ if((fwrq->m > 1000) || (fwrq->e > 0))
+ rc = -EOPNOTSUPP;
+ else {
+ int channel = fwrq->m;
+ if (atmel_validate_channel(priv, channel) == 0) {
+ priv->channel = channel;
+ } else {
+ rc = -EINVAL;
+ }
+ }
+ return rc;
+}
+
+static int atmel_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ fwrq->m = priv->channel;
+ fwrq->e = 0;
+ return 0;
+}
+
+static int atmel_set_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *vwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+
+ /* Note : you may have realised that, as this is a SET operation,
+ * this is privileged and therefore a normal user can't
+ * perform scanning.
+ * This is not an error, while the device perform scanning,
+ * traffic doesn't flow, so it's a perfect DoS...
+ * Jean II */
+
+ if (priv->station_state == STATION_STATE_DOWN ||
+ priv->station_state == STATION_STATE_NO_CARD)
+ return -EAGAIN;
+
+ /* Timeout old surveys. */
+ if ((jiffies - priv->last_survey) > (20 * HZ))
+ priv->site_survey_state = SITE_SURVEY_IDLE;
+ priv->last_survey = jiffies;
+
+ /* Initiate a scan command */
+ if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
+ return -EBUSY;
+
+ priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
+
+ atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+ del_timer_sync(&priv->management_timer);
+ atmel_scan(priv, 0);
+ atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+
+ return 0;
+}
+
+static int atmel_get_scan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int i;
+ char *current_ev = extra;
+ struct iw_event iwe;
+
+ if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
+ return -EAGAIN;
+
+ for(i=0; iBSS_list_entries; i++) {
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
+ current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN);
+
+ iwe.u.data.length = priv->BSSinfo[i].SSIDsize;
+ if (iwe.u.data.length > 32)
+ iwe.u.data.length = 32;
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
+
+ iwe.cmd = SIOCGIWMODE;
+ iwe.u.mode = priv->BSSinfo[i].BSStype;
+ current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
+
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = priv->BSSinfo[i].channel;
+ iwe.u.freq.e = 0;
+ current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
+
+ iwe.cmd = SIOCGIWENCODE;
+ if (priv->BSSinfo[i].UsingWEP)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
+
+ }
+
+ /* Length of data */
+ dwrq->length = (current_ev - extra);
+ dwrq->flags = 0; /* todo */
+
+ return 0;
+}
+
+static int atmel_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ struct iw_range *range = (struct iw_range *) extra;
+ int k,i,j;
+
+ dwrq->length = sizeof(struct iw_range);
+ memset(range, 0, sizeof(range));
+ range->min_nwid = 0x0000;
+ range->max_nwid = 0x0000;
+ range->num_channels = 0;
+ for (j = 0; j < sizeof(channel_table)/sizeof(channel_table[0]); j++)
+ if (priv->reg_domain == channel_table[j].reg_domain) {
+ range->num_channels = channel_table[j].max - channel_table[j].min + 1;
+ }
+ if (range->num_channels != 0) {
+ for(k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
+ range->freq[k].i = i + 1; /* List index */
+ range->freq[k].m = frequency_list[i] * 100000;
+ range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+ }
+ range->num_frequency = k;
+ }
+
+ range->max_qual.qual = 100;
+ range->max_qual.level = 100;
+ range->max_qual.noise = 0;
+ range->sensitivity = 0;
+
+ range->bitrate[0] = 1e6;
+ range->bitrate[1] = 2e6;
+ range->bitrate[2] = 5.5e6;
+ range->bitrate[3] = 11e6;
+ range->num_bitrates = 4;
+
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+
+ range->encoding_size[0] = 5;
+ range->encoding_size[1] = 13;
+ range->num_encoding_sizes = 2;
+ range->max_encoding_tokens = 4;
+
+ range->pmp_flags = IW_POWER_ON;
+ range->pmt_flags = IW_POWER_ON;
+ range->pm_capa = 0;
+
+ range->we_version_source = WIRELESS_EXT;
+ range->we_version_compiled = WIRELESS_EXT;
+ range->retry_capa = IW_RETRY_LIMIT ;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->r_time_flags = 0;
+ range->min_retry = 1;
+ range->max_retry = 65535;
+ range->avg_qual.qual = 50;
+ range->avg_qual.level = 50;
+ range->avg_qual.noise = 0;
+
+ return 0;
+}
+
+static int atmel_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *awrq,
+ char *extra)
+{
+ struct atmel_private *priv = dev->priv;
+ int i;
+ static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
+
+ if (awrq->sa_family != ARPHRD_ETHER)
+ return -EINVAL;
+
+ if (memcmp(bcast, awrq->sa_data, 6) == 0) {
+ atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
+ del_timer_sync(&priv->management_timer);
+ atmel_scan(priv, 1);
+ atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
+ return 0;
+ }
+
+ for(i=0; iBSS_list_entries; i++) {
+ if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
+ if (!priv->wep.wep_is_on && priv->BSSinfo[i].UsingWEP) {
+ return -EINVAL;
+ } else if (priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) {
+ return -EINVAL;
+ } else
+ atmel_join_bss(priv, i);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int atmel_config_commit(struct net_device *dev,
+ struct iw_request_info *info, /* NULL */
+ void *zwrq, /* NULL */
+ char *extra) /* NULL */
+{
+ reset_atmel_card(dev);
+ return 0;
+}
+
+static const iw_handler atmel_handler[] =
+{
+ (iw_handler) atmel_config_commit, /* SIOCSIWCOMMIT */
+ (iw_handler) atmel_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) atmel_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) atmel_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) atmel_set_mode, /* SIOCSIWMODE */
+ (iw_handler) atmel_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) atmel_get_range, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ (iw_handler) NULL, /* SIOCSIWSPY */
+ (iw_handler) NULL, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) atmel_set_wap, /* SIOCSIWAP */
+ (iw_handler) atmel_get_wap, /* SIOCGIWAP */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
+ (iw_handler) atmel_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) atmel_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) atmel_set_essid, /* SIOCSIWESSID */
+ (iw_handler) atmel_get_essid, /* SIOCGIWESSID */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) NULL, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) atmel_set_rate, /* SIOCSIWRATE */
+ (iw_handler) atmel_get_rate, /* SIOCGIWRATE */
+ (iw_handler) atmel_set_rts, /* SIOCSIWRTS */
+ (iw_handler) atmel_get_rts, /* SIOCGIWRTS */
+ (iw_handler) atmel_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) atmel_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) NULL, /* SIOCSIWTXPOW */
+ (iw_handler) NULL, /* SIOCGIWTXPOW */
+ (iw_handler) atmel_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) atmel_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) atmel_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) atmel_set_power, /* SIOCSIWPOWER */
+ (iw_handler) atmel_get_power, /* SIOCGIWPOWER */
+};
+
+
+static const iw_handler atmel_private_handler[] =
+{
+ NULL, /* SIOCIWFIRSTPRIV */
+};
+
+typedef struct atmel_priv_ioctl {
+ char id[32];
+ unsigned char *data;
+ unsigned short len;
+} atmel_priv_ioctl;
+
+
+#define ATMELFWL SIOCIWFIRSTPRIV
+#define ATMELIDIFC ATMELFWL + 1
+#define ATMELMAGIC 0x51807
+
+static const struct iw_priv_args atmel_private_args[] = {
+/*{ cmd, set_args, get_args, name } */
+ { ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
+ { ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
+};
+
+static const struct iw_handler_def atmel_handler_def =
+{
+ .num_standard = sizeof(atmel_handler)/sizeof(iw_handler),
+ .num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
+ .num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
+ .standard = (iw_handler *) atmel_handler,
+ .private = (iw_handler *) atmel_private_handler,
+ .private_args = (struct iw_priv_args *) atmel_private_args
+};
+
+static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ int rc = 0;
+ struct atmel_private *priv = (struct atmel_private *) dev->priv;
+ atmel_priv_ioctl com;
+ struct iwreq *wrq = (struct iwreq *) rq;
+ unsigned char *new_firmware;
+
+ switch (cmd) {
+ case SIOCGIWPRIV:
+ if(wrq->u.data.pointer) {
+ /* Set the number of ioctl available */
+ wrq->u.data.length = sizeof(atmel_private_args) / sizeof(atmel_private_args[0]);
+
+ /* Copy structure to the user buffer */
+ if (copy_to_user(wrq->u.data.pointer,
+ (u_char *) atmel_private_args,
+ sizeof(atmel_private_args)))
+ rc = -EFAULT;
+ }
+ break;
+
+ case ATMELIDIFC:
+ wrq->u.param.value = ATMELMAGIC;
+ break;
+
+ case ATMELFWL:
+ if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
+ rc = -EFAULT;
+ break;
+ }
+
+ if (!capable(CAP_NET_ADMIN)) {
+ rc = -EPERM;
+ break;
+ }
+
+ if (!(new_firmware = kmalloc(com.len, GFP_KERNEL))) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(new_firmware, com.data, com.len)) {
+ rc = -EFAULT;
+ break;
+ }
+
+ if (priv->firmware)
+ kfree(priv->firmware);
+
+ priv->firmware = new_firmware;
+ priv->firmware_length = com.len;
+ strncpy(priv->firmware_id, com.id, 31);
+ priv->firmware_id[31] = '\0';
+ break;
+
+ default:
+ rc = -EOPNOTSUPP;
+ }
+
+ return rc;
+}
+
+struct auth_body {
+ u16 alg;
+ u16 trans_seq;
+ u16 status;
+ u8 el_id;
+ u8 chall_text_len;
+ u8 chall_text[253];
+};
+
+static void atmel_enter_state(struct atmel_private *priv, int new_state)
+{
+ int old_state = priv->station_state;
+
+ if (new_state == old_state)
+ return;
+
+ if (new_state == STATION_STATE_READY)
+ netif_start_queue(priv->dev);
+
+ if (old_state == STATION_STATE_READY) {
+ netif_stop_queue(priv->dev);
+ priv->last_beacon_timestamp = 0;
+ }
+
+ priv->station_state = new_state;
+
+}
+
+static void atmel_scan(struct atmel_private *priv, int specific_ssid)
+{
+ struct {
+ u8 BSSID[6];
+ u8 SSID[MAX_SSID_LENGTH];
+ u8 scan_type;
+ u8 channel;
+ u16 BSS_type;
+ u16 min_channel_time;
+ u16 max_channel_time;
+ u8 options;
+ u8 SSID_size;
+ } cmd;
+
+ atmel_enter_state(priv, STATION_STATE_SCANNING);
+
+ memset(cmd.BSSID, 0xff, 6);
+
+ if (priv->fast_scan) {
+ cmd.SSID_size = priv->SSID_size;
+ memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+ cmd.min_channel_time = cpu_to_le16(10);
+ cmd.max_channel_time = cpu_to_le16(50);
+ } else {
+ priv->BSS_list_entries = 0;
+ cmd.SSID_size = 0;
+ cmd.min_channel_time = cpu_to_le16(10);
+ cmd.max_channel_time = cpu_to_le16(120);
+ }
+
+ cmd.options = 0;
+
+ if (!specific_ssid)
+ cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
+
+ cmd.channel = (priv->channel & 0x7f);
+ cmd.scan_type = SCAN_TYPE_ACTIVE;
+ cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
+ BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
+
+ atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
+}
+
+static void join(struct atmel_private *priv, int type)
+{
+ struct {
+ u8 BSSID[6];
+ u8 SSID[MAX_SSID_LENGTH];
+ u8 BSS_type; /* this is a short in a scan command - wierd */
+ u8 channel;
+ u16 timeout;
+ u8 SSID_size;
+ u8 reserved;
+ } cmd;
+
+ cmd.SSID_size = priv->SSID_size;
+ memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+ memcpy(cmd.BSSID, priv->CurrentBSSID, 6);
+ cmd.channel = (priv->channel & 0x7f);
+ cmd.BSS_type = type;
+ cmd.timeout = cpu_to_le16(2000);
+
+ atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
+}
+
+
+static void start(struct atmel_private *priv, int type)
+{
+ struct {
+ u8 BSSID[6];
+ u8 SSID[MAX_SSID_LENGTH];
+ u8 BSS_type;
+ u8 channel;
+ u8 SSID_size;
+ u8 reserved[3];
+ } cmd;
+
+ cmd.SSID_size = priv->SSID_size;
+ memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
+ memcpy(cmd.BSSID, priv->BSSID, 6);
+ cmd.BSS_type = type;
+ cmd.channel = (priv->channel & 0x7f);
+
+ atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
+}
+
+static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel)
+{
+ int rejoin = 0;
+ int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+ SHORT_PREAMBLE : LONG_PREAMBLE;
+
+ if (priv->preamble != new) {
+ priv->preamble = new;
+ rejoin = 1;
+ atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
+ }
+
+ if (priv->channel != channel) {
+ priv->channel = channel;
+ rejoin = 1;
+ atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
+ }
+
+ if (rejoin) {
+ priv->station_is_associated = 0;
+ atmel_enter_state(priv, STATION_STATE_JOINNING);
+
+ if (priv->operating_mode == IW_MODE_INFRA)
+ join(priv, BSS_TYPE_INFRASTRUCTURE);
+ else
+ join(priv, BSS_TYPE_AD_HOC);
+ }
+}
+
+
+static void send_authentication_request(struct atmel_private *priv, u8 *challenge, int challenge_len)
+{
+ struct ieee802_11_hdr header;
+ struct auth_body auth;
+
+ header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH);
+ header.duration_id = cpu_to_le16(0x8000);
+ header.seq_ctl = 0;
+ memcpy(header.addr1, priv->CurrentBSSID, 6);
+ memcpy(header.addr2, priv->dev->dev_addr, 6);
+ memcpy(header.addr3, priv->CurrentBSSID, 6);
+
+ if (priv->wep.wep_is_on) {
+ auth.alg = C80211_MGMT_AAN_SHAREDKEY;
+ /* no WEP for authentication frames with TrSeqNo 1 */
+ if (priv->CurrentAuthentTransactionSeqNum != 1)
+ header.frame_ctl |= cpu_to_le16(IEEE802_11_FCTL_WEP);
+ } else {
+ auth.alg = C80211_MGMT_AAN_OPENSYSTEM;
+ }
+
+ auth.status = 0;
+ auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
+ priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
+ priv->CurrentAuthentTransactionSeqNum += 2;
+
+ if (challenge_len != 0) {
+ auth.el_id = 16; /* challenge_text */
+ auth.chall_text_len = challenge_len;
+ memcpy(auth.chall_text, challenge, challenge_len);
+ atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 8 + challenge_len);
+ } else {
+ atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 6);
+ }
+}
+
+static void send_association_request(struct atmel_private *priv, int is_reassoc)
+{
+ u8 *ssid_el_p;
+ int bodysize;
+ struct ieee802_11_hdr header;
+ struct ass_req_format {
+ u16 capability;
+ u16 listen_interval;
+ u8 ap[6]; /* nothing after here directly accessible */
+ u8 ssid_el_id;
+ u8 ssid_len;
+ u8 ssid[MAX_SSID_LENGTH];
+ u8 sup_rates_el_id;
+ u8 sup_rates_len;
+ u8 rates[4];
+ } body;
+
+ header.frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT |
+ (is_reassoc ? IEEE802_11_STYPE_REASSOC_REQ : IEEE802_11_STYPE_ASSOC_REQ));
+ header.duration_id = cpu_to_le16(0x8000);
+ header.seq_ctl = 0;
+
+ memcpy(header.addr1, priv->CurrentBSSID, 6);
+ memcpy(header.addr2, priv->dev->dev_addr, 6);
+ memcpy(header.addr3, priv->CurrentBSSID, 6);
+
+ body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
+ if (priv->wep.wep_is_on)
+ body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy);
+ if (priv->preamble == SHORT_PREAMBLE)
+ body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
+
+ body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
+
+ /* current AP address - only in reassoc frame */
+ if (is_reassoc) {
+ memcpy(body.ap, priv->CurrentBSSID, 6);
+ ssid_el_p = (u8 *)&body.ssid_el_id;
+ bodysize = 18 + priv->SSID_size;
+ } else {
+ ssid_el_p = (u8 *)&body.ap[0];
+ bodysize = 12 + priv->SSID_size;
+ }
+
+ ssid_el_p[0]= C80211_MGMT_ElementID_SSID;
+ ssid_el_p[1] = priv->SSID_size;
+ memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
+ ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
+ ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
+ memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
+
+ atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
+}
+
+static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee802_11_hdr *header)
+{
+ if (le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_FROMDS)
+ return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
+ else
+ return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
+}
+
+static int retrieve_bss(struct atmel_private *priv)
+{
+ int i;
+ int max_rssi = -128;
+ int max_index = -1;
+
+ if (priv->BSS_list_entries == 0)
+ return -1;
+
+ if (priv->connect_to_any_BSS) {
+ /* Select a BSS with the max-RSSI but of the same type and of the same WEP mode
+ and that it is not marked as 'bad' (i.e. we had previously failed to connect to
+ this BSS with the settings that we currently use) */
+ priv->current_BSS = 0;
+ for(i=0; iBSS_list_entries; i++) {
+ if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
+ ((!priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
+ (priv->wep.wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
+ !(priv->BSSinfo[i].channel & 0x80)) {
+ max_rssi = priv->BSSinfo[i].RSSI;
+ priv->current_BSS = max_index = i;
+ }
+
+ }
+ return max_index;
+ }
+
+ for(i=0; iBSS_list_entries; i++) {
+ if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
+ memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
+ priv->operating_mode == priv->BSSinfo[i].BSStype &&
+ atmel_validate_channel(priv, priv->BSSinfo[i].channel) == 0) {
+ if (priv->BSSinfo[i].RSSI >= max_rssi) {
+ max_rssi = priv->BSSinfo[i].RSSI;
+ max_index = i;
+ }
+ }
+ }
+ return max_index;
+}
+
+
+static void store_bss_info(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u16 capability, u16 beacon_period, u8 channel, u8 rssi,
+ u8 ssid_len, u8 *ssid, int is_beacon)
+{
+ u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
+ int i, index;
+
+ for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
+ if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
+ index = i;
+
+ /* If we process a probe and an entry from this BSS exists
+ we will update the BSS entry with the info from this BSS.
+ If we process a beacon we will only update RSSI */
+
+ if (index == -1) {
+ if (priv->BSS_list_entries == MAX_BSS_ENTRIES)
+ return;
+ index = priv->BSS_list_entries++;
+ memcpy(priv->BSSinfo[index].BSSID, bss, 6);
+ priv->BSSinfo[index].RSSI = rssi;
+ } else {
+ if (rssi > priv->BSSinfo[index].RSSI)
+ priv->BSSinfo[index].RSSI = rssi;
+ if (is_beacon)
+ return;
+ }
+
+ priv->BSSinfo[index].channel = channel;
+ priv->BSSinfo[index].beacon_period = beacon_period;
+ priv->BSSinfo[index].UsingWEP = capability & C80211_MGMT_CAPABILITY_Privacy;
+ memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
+ priv->BSSinfo[index].SSIDsize = ssid_len;
+
+ if (capability & C80211_MGMT_CAPABILITY_IBSS)
+ priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
+ else if (capability & C80211_MGMT_CAPABILITY_ESS)
+ priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
+
+ priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+ SHORT_PREAMBLE : LONG_PREAMBLE;
+}
+
+static void authenticate(struct atmel_private *priv, u16 frame_len)
+{
+ struct auth_body *auth = (struct auth_body *)priv->rx_buf;
+ u16 status = le16_to_cpu(auth->status);
+ u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
+
+ if (status == C80211_MGMT_SC_Success && !priv->wep.wep_is_on) {
+ /* no WEP */
+ if (priv->station_was_associated) {
+ atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
+ send_association_request(priv, 1);
+ return;
+ } else {
+ atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
+ send_association_request(priv, 0);
+ return;
+ }
+ }
+
+ if (status == C80211_MGMT_SC_Success && priv->wep.wep_is_on) {
+ /* WEP */
+ if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
+ return;
+
+ if (trans_seq_no == 0x0002 &&
+ auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
+ send_authentication_request(priv, auth->chall_text, auth->chall_text_len);
+ return;
+ }
+
+ if (trans_seq_no == 0x0004) {
+ if(priv->station_was_associated) {
+ atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
+ send_association_request(priv, 1);
+ return;
+ } else {
+ atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
+ send_association_request(priv, 0);
+ return;
+ }
+ }
+ }
+
+ if (status == C80211_MGMT_SC_AuthAlgNotSupported && priv->connect_to_any_BSS) {
+ int bss_index;
+
+ priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+
+ if ((bss_index = retrieve_bss(priv)) != -1) {
+ atmel_join_bss(priv, bss_index);
+ return;
+ }
+ }
+
+
+ priv->AuthenticationRequestRetryCnt = 0;
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+}
+
+static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
+{
+ struct ass_resp_format {
+ u16 capability;
+ u16 status;
+ u16 ass_id;
+ u8 el_id;
+ u8 length;
+ u8 rates[4];
+ } *ass_resp = (struct ass_resp_format *)priv->rx_buf;
+
+ u16 status = le16_to_cpu(ass_resp->status);
+ u16 ass_id = le16_to_cpu(ass_resp->ass_id);
+ u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
+
+ if (frame_len < 8 + rates_len)
+ return;
+
+ if (status == C80211_MGMT_SC_Success) {
+ if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
+ priv->AssociationRequestRetryCnt = 0;
+ else
+ priv->ReAssociationRequestRetryCnt = 0;
+
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
+ atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
+ if (priv->power_mode == 0) {
+ priv->listen_interval = 1;
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+ } else {
+ priv->listen_interval = 2;
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, PS_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
+ }
+
+ priv->station_is_associated = 1;
+ priv->station_was_associated = 1;
+ atmel_enter_state(priv, STATION_STATE_READY);
+ return;
+ }
+
+ if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
+ status != C80211_MGMT_SC_AssDeniedBSSRate &&
+ status != C80211_MGMT_SC_SupportCapabilities &&
+ priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ priv->AssociationRequestRetryCnt++;
+ send_association_request(priv, 0);
+ return;
+ }
+
+ if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
+ status != C80211_MGMT_SC_AssDeniedBSSRate &&
+ status != C80211_MGMT_SC_SupportCapabilities &&
+ priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ priv->ReAssociationRequestRetryCnt++;
+ send_association_request(priv, 1);
+ return;
+ }
+
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+
+ if(priv->connect_to_any_BSS) {
+ int bss_index;
+ priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+
+ if ((bss_index = retrieve_bss(priv)) != -1)
+ atmel_join_bss(priv, bss_index);
+
+ }
+}
+
+void atmel_join_bss(struct atmel_private *priv, int bss_index)
+{
+ struct bss_info *bss = &priv->BSSinfo[bss_index];
+
+ memcpy(priv->CurrentBSSID, bss->BSSID, 6);
+ memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize);
+
+ /* When switching to AdHoc turn OFF Power Save if needed */
+
+ if (bss->BSStype == IW_MODE_ADHOC &&
+ priv->operating_mode != IW_MODE_ADHOC &&
+ priv->power_mode) {
+ priv->power_mode = 0;
+ priv->listen_interval = 1;
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+ }
+
+ priv->operating_mode = bss->BSStype;
+ priv->channel = bss->channel & 0x7f;
+ priv->beacon_period = bss->beacon_period;
+
+ if (priv->preamble != bss->preamble) {
+ priv->preamble = bss->preamble;
+ atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
+ }
+
+ if (!priv->wep.wep_is_on && bss->UsingWEP) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ return;
+ }
+
+ if (priv->wep.wep_is_on && !bss->UsingWEP) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ return;
+ }
+
+ atmel_enter_state(priv, STATION_STATE_JOINNING);
+
+ if (priv->operating_mode == IW_MODE_INFRA)
+ join(priv, BSS_TYPE_INFRASTRUCTURE);
+ else
+ join(priv, BSS_TYPE_AD_HOC);
+}
+
+
+static void restart_search(struct atmel_private *priv)
+{
+ int bss_index;
+
+ if (!priv->connect_to_any_BSS) {
+ atmel_scan(priv, 1);
+ } else {
+ priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
+
+ if ((bss_index = retrieve_bss(priv)) != -1)
+ atmel_join_bss(priv, bss_index);
+ else
+ atmel_scan(priv, 0);
+
+ }
+}
+
+static void smooth_rssi(struct atmel_private *priv, u8 rssi)
+{
+ u8 old = priv->wstats.qual.level;
+
+ /* 502-rmfd-revd gives max signal level as 42, by experiment.
+ This is going to break for other hardware variants. */
+
+ rssi = rssi * 100 / 42;
+ if((rssi + old) % 2)
+ priv->wstats.qual.level = ((rssi + old)/2) + 1;
+ else
+ priv->wstats.qual.level = ((rssi + old)/2);
+
+}
+
+static void atmel_smooth_qual(struct atmel_private *priv)
+{
+ unsigned long time_diff = (jiffies - priv->last_qual)/HZ;
+ while (time_diff--) {
+ priv->last_qual += HZ;
+ priv->wstats.qual.qual = priv->wstats.qual.qual/2;
+ priv->wstats.qual.qual +=
+ priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
+ priv->beacons_this_sec = 0;
+ }
+}
+
+/* deals with incoming managment frames. */
+static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header,
+ u16 frame_len, u8 rssi)
+{
+ u16 subtype;
+
+ switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE802_11_FCTL_STYPE) {
+ case C80211_SUBTYPE_MGMT_BEACON :
+ case C80211_SUBTYPE_MGMT_ProbeResponse:
+
+ /* beacon frame has multiple variable-length fields -
+ never let an engineer loose with a data structure design. */
+ {
+ struct beacon_format {
+ u64 timestamp;
+ u16 interval;
+ u16 capability;
+ u8 ssid_el_id;
+ u8 ssid_length;
+ /* ssid here */
+ u8 rates_el_id;
+ u8 rates_length;
+ /* rates here */
+ u8 ds_el_id;
+ u8 ds_length;
+ /* ds here */
+ } *beacon = (struct beacon_format *)priv->rx_buf;
+
+ u8 channel, rates_length, ssid_length;
+ u64 timestamp = le64_to_cpu(beacon->timestamp);
+ u16 beacon_interval = le16_to_cpu(beacon->interval);
+ u16 capability = le16_to_cpu(beacon->capability);
+ u8 *beaconp = priv->rx_buf;
+ ssid_length = beacon->ssid_length;
+ /* this blows chunks. */
+ if (frame_len < 14 || frame_len < ssid_length + 15)
+ return;
+ rates_length = beaconp[beacon->ssid_length + 15];
+ if (frame_len < ssid_length + rates_length + 18)
+ return;
+ if (ssid_length > MAX_SSID_LENGTH)
+ return;
+ channel = beaconp[ssid_length + rates_length + 18];
+
+ if (priv->station_state == STATION_STATE_READY) {
+ smooth_rssi(priv, rssi);
+ if (is_frame_from_current_bss(priv, header)) {
+ priv->beacons_this_sec++;
+ atmel_smooth_qual(priv);
+ if (priv->last_beacon_timestamp) {
+ /* Note truncate this to 32 bits - kernel can't divide a long long */
+ u32 beacon_delay = timestamp - priv->last_beacon_timestamp;
+ int beacons = beacon_delay / (beacon_interval * 1000);
+ if (beacons > 1)
+ priv->wstats.miss.beacon += beacons - 1;
+ }
+ priv->last_beacon_timestamp = timestamp;
+ handle_beacon_probe(priv, capability, channel);
+ }
+ }
+
+ if (priv->station_state == STATION_STATE_SCANNING )
+ store_bss_info(priv, header, capability, beacon_interval, channel,
+ rssi, ssid_length, &beacon->rates_el_id,
+ subtype == C80211_SUBTYPE_MGMT_BEACON) ;
+ }
+ break;
+
+ case C80211_SUBTYPE_MGMT_Authentication:
+
+ if (priv->station_state == STATION_STATE_AUTHENTICATING)
+ authenticate(priv, frame_len);
+
+ break;
+
+ case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
+ case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
+
+ if (priv->station_state == STATION_STATE_ASSOCIATING ||
+ priv->station_state == STATION_STATE_REASSOCIATING)
+ associate(priv, frame_len, subtype);
+
+ break;
+
+ case C80211_SUBTYPE_MGMT_DISASSOSIATION:
+ if (priv->station_is_associated &&
+ priv->operating_mode == IW_MODE_INFRA &&
+ is_frame_from_current_bss(priv, header)) {
+ priv->station_was_associated = 0;
+ priv->station_is_associated = 0;
+
+ atmel_enter_state(priv, STATION_STATE_JOINNING);
+ join(priv, BSS_TYPE_INFRASTRUCTURE);
+ }
+
+ break;
+
+ case C80211_SUBTYPE_MGMT_Deauthentication:
+ if (priv->operating_mode == IW_MODE_INFRA &&
+ is_frame_from_current_bss(priv, header)) {
+ priv->station_was_associated = 0;
+
+ atmel_enter_state(priv, STATION_STATE_JOINNING);
+ join(priv, BSS_TYPE_INFRASTRUCTURE);
+ }
+
+ break;
+ }
+}
+
+/* run when timer expires */
+static void atmel_management_timer(u_long a)
+{
+ struct net_device *dev = (struct net_device *) a;
+ struct atmel_private *priv = (struct atmel_private *)dev->priv;
+ unsigned long flags;
+
+ /* Check if the card has been yanked. */
+ if (priv->card && priv->present_callback &&
+ !(*priv->present_callback)(priv->card))
+ return;
+
+ if (priv->station_state == STATION_STATE_NO_CARD)
+ return;
+
+ spin_lock_irqsave(&priv->irqlock, flags);
+
+ switch (priv->station_state) {
+
+ case STATION_STATE_AUTHENTICATING:
+
+ if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->AuthenticationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->AuthenticationRequestRetryCnt++;
+ priv->CurrentAuthentTransactionSeqNum = 0x0001;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_authentication_request(priv, NULL, 0);
+ }
+
+ break;
+
+ case STATION_STATE_ASSOCIATING:
+
+ if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->AssociationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->AssociationRequestRetryCnt++;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_association_request(priv, 0);
+ }
+
+ break;
+
+ case STATION_STATE_REASSOCIATING:
+
+ if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->ReAssociationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->ReAssociationRequestRetryCnt++;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_association_request(priv, 1);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ spin_unlock_irqrestore(&priv->irqlock, flags);
+}
+
+static void atmel_command_irq(struct atmel_private *priv)
+{
+ u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
+ u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
+ int fast_scan;
+
+ if (status == CMD_STATUS_IDLE ||
+ status == CMD_STATUS_IN_PROGRESS)
+ return;
+
+ switch (command){
+
+ case CMD_Start:
+ if (status == CMD_STATUS_COMPLETE) {
+ priv->station_was_associated = priv->station_is_associated;
+ atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
+ (u8 *)priv->CurrentBSSID, 6);
+ atmel_enter_state(priv, STATION_STATE_READY);
+ }
+ break;
+
+ case CMD_Scan:
+ fast_scan = priv->fast_scan;
+ priv->fast_scan = 0;
+
+ if (status != CMD_STATUS_COMPLETE) {
+ atmel_scan(priv, 1);
+ } else {
+ int bss_index = retrieve_bss(priv);
+ if (bss_index != -1) {
+ atmel_join_bss(priv, bss_index);
+ } else if (priv->operating_mode == IW_MODE_ADHOC &&
+ priv->SSID_size != 0) {
+ start(priv, BSS_TYPE_AD_HOC);
+ } else {
+ priv->fast_scan = !fast_scan;
+ atmel_scan(priv, 1);
+ }
+ }
+ break;
+
+ case CMD_SiteSurvey:
+ priv->fast_scan = 0;
+
+ if (status != CMD_STATUS_COMPLETE)
+ return;
+
+ priv->site_survey_state = SITE_SURVEY_COMPLETED;
+ if (priv->station_is_associated) {
+ atmel_enter_state(priv, STATION_STATE_READY);
+ } else {
+ atmel_scan(priv, 1);
+ }
+ break;
+
+ case CMD_Join:
+ if (status == CMD_STATUS_COMPLETE) {
+ if (priv->operating_mode == IW_MODE_ADHOC) {
+ priv->station_was_associated = priv->station_is_associated;
+ atmel_enter_state(priv, STATION_STATE_READY);
+ } else {
+ priv->AuthenticationRequestRetryCnt = 0;
+ atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
+
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ priv->CurrentAuthentTransactionSeqNum = 0x0001;
+ send_authentication_request(priv, NULL, 0);
+ }
+ return;
+ }
+
+
+ if (priv->station_state == STATION_STATE_FORCED_JOINNING) {
+ atmel_enter_state(priv, STATION_STATE_FORCED_JOIN_FAILURE);
+ } else {
+ atmel_scan(priv, 1);
+ }
+ }
+}
+
+static int atmel_wakeup_firmware(struct atmel_private *priv)
+{
+ struct host_info_struct *iface = &priv->host_info;
+ u16 mr1, mr3;
+ int i;
+
+ if (priv->card_type == CARD_TYPE_SPI_FLASH)
+ atmel_set_gcr(priv->dev, GCR_REMAP);
+
+ /* wake up on-board processor */
+ atmel_clear_gcr(priv->dev, 0x0040);
+ atmel_write16(priv->dev, BSR, BSS_SRAM);
+
+ if (priv->card_type == CARD_TYPE_SPI_FLASH)
+ mdelay(100);
+
+ /* and wait for it */
+ for (i = LOOP_RETRY_LIMIT; i; i--) {
+ mr1 = atmel_read16(priv->dev, MR1);
+ mr3 = atmel_read16(priv->dev, MR3);
+
+ if (mr3 & MAC_BOOT_COMPLETE)
+ break;
+ if (mr1 & MAC_BOOT_COMPLETE &&
+ priv->bus_type == BUS_TYPE_PCCARD)
+ break;
+ }
+
+ if (i == 0) {
+ printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
+ return 0;
+ }
+
+ if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
+ printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
+ priv->station_state = STATION_STATE_NO_CARD;
+ return 0;
+ }
+
+ /* now check for completion of MAC initialization through
+ the FunCtrl field of the IFACE, poll MR1 to detect completion of
+ MAC initialization, check completion status, set interrupt mask,
+ enables interrupts and calls Tx and Rx initialization functions */
+
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
+
+ for (i = LOOP_RETRY_LIMIT; i; i--) {
+ mr1 = atmel_read16(priv->dev, MR1);
+ mr3 = atmel_read16(priv->dev, MR3);
+
+ if (mr3 & MAC_INIT_COMPLETE)
+ break;
+ if (mr1 & MAC_INIT_COMPLETE &&
+ priv->bus_type == BUS_TYPE_PCCARD)
+ break;
+ }
+
+ if (i == 0) {
+ printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name);
+ return 0;
+ }
+
+ /* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
+ if ((mr3 & MAC_INIT_COMPLETE) &&
+ !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
+ printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
+ return 0;
+ }
+ if ((mr1 & MAC_INIT_COMPLETE) &&
+ !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
+ printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
+ return 0;
+ }
+
+ atmel_copy_to_host(priv->dev, (unsigned char *)iface,
+ priv->host_info_base, sizeof(*iface));
+
+ iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
+ iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
+ iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
+ iface->tx_desc_count = le16_to_cpu(iface->tx_desc_count);
+ iface->rx_buff_pos = le16_to_cpu(iface->rx_buff_pos);
+ iface->rx_buff_size = le16_to_cpu(iface->rx_buff_size);
+ iface->rx_desc_pos = le16_to_cpu(iface->rx_desc_pos);
+ iface->rx_desc_count = le16_to_cpu(iface->rx_desc_count);
+ iface->build_version = le16_to_cpu(iface->build_version);
+ iface->command_pos = le16_to_cpu(iface->command_pos);
+ iface->major_version = le16_to_cpu(iface->major_version);
+ iface->minor_version = le16_to_cpu(iface->minor_version);
+ iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
+ iface->mac_status = le16_to_cpu(iface->mac_status);
+
+ return 1;
+}
+
+/* determine type of memory and MAC address */
+static int probe_atmel_card(struct net_device *dev)
+{
+ int rc = 0;
+ struct atmel_private *priv = dev->priv;
+
+ /* reset pccard */
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(dev, GCR, 0x0060);
+
+ atmel_write16(dev, GCR, 0x0040);
+ mdelay(500);
+
+ if (atmel_read16(dev, MR2) == 0) {
+ /* No stored firmware so load a small stub which just
+ tells us the MAC address */
+ int i;
+ priv->card_type = CARD_TYPE_EEPROM;
+ atmel_write16(dev, BSR, BSS_IRAM);
+ atmel_copy_to_card(dev, 0, mac_reader, sizeof(mac_reader));
+ atmel_set_gcr(dev, GCR_REMAP);
+ atmel_clear_gcr(priv->dev, 0x0040);
+ atmel_write16(dev, BSR, BSS_SRAM);
+ for (i = LOOP_RETRY_LIMIT; i; i--)
+ if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
+ break;
+ if (i == 0) {
+ printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
+ } else {
+ atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
+
+ /* got address, now squash it again until the network
+ interface is opened */
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(dev, GCR, 0x0060);
+ atmel_write16(dev, GCR, 0x0040);
+ rc = 1;
+ }
+ } else if (atmel_read16(dev, MR4) == 0) {
+ /* Mac address easy in this case. */
+ priv->card_type = CARD_TYPE_PARALLEL_FLASH;
+ atmel_write16(dev, BSR, 1);
+ atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
+ atmel_write16(dev, BSR, 0x200);
+ rc = 1;
+ } else {
+ /* Standard firmware in flash, boot it up and ask
+ for the Mac Address */
+ priv->card_type = CARD_TYPE_SPI_FLASH;
+ if (atmel_wakeup_firmware(priv)) {
+ atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
+
+ /* got address, now squash it again until the network
+ interface is opened */
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(dev, GCR, 0x0060);
+ atmel_write16(dev, GCR, 0x0040);
+ rc = 1;
+ }
+ }
+
+ if (rc) {
+ if (dev->dev_addr[0] == 0xFF) {
+ u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00};
+ printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
+ memcpy(dev->dev_addr, default_mac, 6);
+ }
+ printk(KERN_INFO "%s: MAC address %x:%x:%x:%x:%x:%x\n",
+ dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
+
+ }
+
+ return rc;
+}
+
+int reset_atmel_card(struct net_device *dev)
+{
+ /* do everything necessary to wake up the hardware, including
+ waiting for the lightning strike and throwing the knife switch....
+
+ set all the Mib values which matter in the card to match
+ their settings in the atmel_private structure. Some of these
+ can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
+ can only be changed by tearing down the world and coming back through
+ here.
+
+ This routine is also responsible for initialising some
+ hardware-specific fields in the atmel_private structure,
+ including a copy of the firmware's hostinfo stucture
+ which is the route into the rest of the firmare datastructures. */
+
+ int channel;
+ struct atmel_private *priv = dev->priv;
+ u8 configuration;
+
+ if (priv->station_state == STATION_STATE_NO_CARD ||
+ priv->station_state == STATION_STATE_DOWN)
+ return 0;
+
+ /* reset pccard */
+ if (priv->bus_type == BUS_TYPE_PCCARD)
+ atmel_write16(priv->dev, GCR, 0x0060);
+
+ /* stop card , disable interrupts */
+ atmel_write16(priv->dev, GCR, 0x0040);
+
+ /* any scheduled timer is no longer needed and might screw things up.. */
+ del_timer_sync(&priv->management_timer);
+ if (priv->new_SSID_size) {
+ memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
+ priv->SSID_size = priv->new_SSID_size;
+ priv->new_SSID_size = 0;
+ }
+ priv->BSS_list_entries = 0;
+
+ priv->AuthenticationRequestRetryCnt = 0;
+ priv->AssociationRequestRetryCnt = 0;
+ priv->ReAssociationRequestRetryCnt = 0;
+ priv->CurrentAuthentTransactionSeqNum = 0x0001;
+ priv->ExpectedAuthentTransactionSeqNum = 0x0002;
+
+ priv->station_state = STATION_STATE_INITIALIZING;
+ priv->site_survey_state = SITE_SURVEY_IDLE;
+ priv->station_is_associated = 0;
+
+ if (priv->card_type == CARD_TYPE_EEPROM) {
+ /* copy in firmware if needed */
+#ifdef CONFIG_FW_LOADER
+ const struct firmware *fw_entry = NULL;
+#endif
+ unsigned char *fw;
+ int len = priv->firmware_length;
+ if (!(fw = priv->firmware)) {
+#ifdef CONFIG_FW_LOADER
+ if (strlen(priv->firmware_id) == 0) {
+ printk(KERN_INFO
+ "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
+ dev->name);
+ printk(KERN_INFO
+ "%s: if not, use the firmware= module parameter.\n",
+ dev->name);
+ strcpy(priv->firmware_id, "atmel_at76c502.bin");
+ }
+ if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) {
+ printk(KERN_ALERT
+ "%s: firmware %s is missing, cannot start.\n",
+ dev->name, priv->firmware_id);
+ return 0;
+ }
+ fw = fw_entry->data;
+ len = fw_entry->size;
+#else
+ printk(KERN_ALERT
+ "%s: no firmware supplied, cannot start.\n", dev->name);
+ return 0;
+#endif
+ }
+
+ if (len <= 0x6000) {
+ atmel_write16(priv->dev, BSR, BSS_IRAM);
+ atmel_copy_to_card(priv->dev, 0, fw, len);
+ atmel_set_gcr(priv->dev, GCR_REMAP);
+ } else {
+ /* Remap */
+ atmel_set_gcr(priv->dev, GCR_REMAP);
+ atmel_write16(priv->dev, BSR, BSS_IRAM);
+ atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
+ atmel_write16(priv->dev, BSR, 0x2ff);
+ atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000);
+ }
+
+#ifdef CONFIG_FW_LOADER
+ if (fw_entry)
+ release_firmware(fw_entry);
+#endif
+ }
+
+ if (!atmel_wakeup_firmware(priv))
+ return 0;
+
+ /* unmask all irq sources */
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
+
+ /* int Tx system and enable Tx */
+ atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
+ atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
+ atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
+ atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
+
+ priv->tx_desc_free = priv->host_info.tx_desc_count;
+ priv->tx_desc_head = 0;
+ priv->tx_desc_tail = 0;
+ priv->tx_desc_previous = 0;
+ priv->tx_free_mem = priv->host_info.tx_buff_size;
+ priv->tx_buff_head = 0;
+ priv->tx_buff_tail = 0;
+
+ configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
+ configuration | FUNC_CTRL_TxENABLE);
+
+ /* init Rx system and enable */
+ priv->rx_desc_head = 0;
+
+ configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
+ configuration | FUNC_CTRL_RxENABLE);
+
+ priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
+ if (priv->reg_domain != REG_DOMAIN_FCC &&
+ priv->reg_domain != REG_DOMAIN_DOC &&
+ priv->reg_domain != REG_DOMAIN_ETSI &&
+ priv->reg_domain != REG_DOMAIN_SPAIN &&
+ priv->reg_domain != REG_DOMAIN_FRANCE &&
+ priv->reg_domain != REG_DOMAIN_MKK &&
+ priv->reg_domain != REG_DOMAIN_MKK1 &&
+ priv->reg_domain != REG_DOMAIN_ISRAEL) {
+ priv->reg_domain = REG_DOMAIN_MKK1;
+ printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
+ }
+ if ((channel = atmel_validate_channel(priv, priv->channel)))
+ priv->channel = channel;
+
+ if (!priv->is3com) {
+ if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
+ CMD_STATUS_REJECTED_RADIO_OFF) {
+ printk(KERN_INFO
+ "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
+ dev->name);
+ return 0;
+ }
+ }
+
+ /* set up enough MIB values to run. */
+ atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
+ atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_TX_PROMISCUOUS_POS, PROM_MODE_OFF);
+ atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_RTS_THRESHOLD_POS, priv->rts_threshold);
+ atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_FRAG_THRESHOLD_POS, priv->frag_threshold);
+ atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
+ atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
+ atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
+ atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
+ priv->dev->dev_addr, 6);
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period);
+ atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4);
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep.wep_is_on);
+ atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&priv->wep, sizeof(priv->wep));
+
+ atmel_scan(priv, 1);
+
+ atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
+
+ return 1;
+}
+
+EXPORT_SYMBOL(reset_atmel_card);
+
+static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+{
+ if (cmd)
+ atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
+ cmd, cmd_size);
+
+ atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
+ atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
+}
+
+static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+{
+ int i, status;
+
+ atmel_send_command(priv, command, cmd, cmd_size);
+
+ for (i = LOOP_RETRY_LIMIT; i; i--) {
+ status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
+ if (status != CMD_STATUS_IDLE &&
+ status != CMD_STATUS_IN_PROGRESS)
+ break;
+ }
+
+ if (i == 0) {
+ printk(KERN_ALERT "%s: command %d failed to complete.\n", priv->dev->name, command);
+ status = CMD_STATUS_HOST_ERROR;
+ } else {
+ if (command != CMD_EnableRadio)
+ status = CMD_STATUS_COMPLETE;
+ }
+
+ return status;
+}
+
+static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index)
+{
+ struct get_set_mib m;
+ m.type = type;
+ m.size = 1;
+ m.index = index;
+
+ atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
+ return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4));
+}
+
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data)
+{
+ struct get_set_mib m;
+ m.type = type;
+ m.size = 1;
+ m.index = index;
+ m.data[0] = data;
+
+ atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data)
+{
+ struct get_set_mib m;
+ m.type = type;
+ m.size = 2;
+ m.index = index;
+ m.data[0] = data;
+ m.data[1] = data >> 8;
+
+ atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+{
+ struct get_set_mib m;
+ m.type = type;
+ m.size = data_len;
+ m.index = index;
+
+ memcpy(m.data, data, data_len);
+ atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
+}
+
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+{
+ struct get_set_mib m;
+ m.type = type;
+ m.size = data_len;
+ m.index = index;
+
+ atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
+ atmel_copy_to_host(priv->dev, data, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4), data_len);
+}
+
+static void atmel_writeAR(struct net_device *dev, u16 data)
+{
+ int i;
+ outw(data, dev->base_addr + AR);
+ /* Address register appears to need some convincing..... */
+ for (i = 0; data != inw(dev->base_addr + AR) && i<10; i++)
+ outw(data, dev->base_addr + AR);
+}
+
+static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len)
+{
+ int i;
+ atmel_writeAR(dev, dest);
+ if (dest % 2) {
+ atmel_write8(dev, DR, *src);
+ src++; len--;
+ }
+ for (i = len; i > 1 ; i -= 2) {
+ u8 lb = *src++;
+ u8 hb = *src++;
+ atmel_write16(dev, DR, lb | (hb << 8));
+ }
+ if (i)
+ atmel_write8(dev, DR, *src);
+}
+
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len)
+{
+ int i;
+ atmel_writeAR(dev, src);
+ if (src % 2) {
+ *dest = atmel_read8(dev, DR);
+ dest++; len--;
+ }
+ for (i = len; i > 1 ; i -= 2) {
+ u16 hw = atmel_read16(dev, DR);
+ *dest++ = hw;
+ *dest++ = hw >> 8;
+ }
+ if (i)
+ *dest = atmel_read8(dev, DR);
+}
+
+static void atmel_set_gcr(struct net_device *dev, u16 mask)
+{
+ outw(inw(dev->base_addr + GCR) | mask, dev->base_addr + GCR);
+}
+
+static void atmel_clear_gcr(struct net_device *dev, u16 mask)
+{
+ outw(inw(dev->base_addr + GCR) & ~mask, dev->base_addr + GCR);
+}
+
+static int atmel_lock_mac(struct atmel_private *priv)
+{
+ int i, j = 100;
+ retry:
+ for (i = LOOP_RETRY_LIMIT ; atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)) && i ; i--);
+
+ if (!i) return 0; /* timed out */
+
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
+ if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
+ if (!j--) return 0; /* timed out */
+ goto retry;
+ }
+
+ return 1;
+}
+
+static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
+{
+ atmel_writeAR(priv->dev, pos);
+ atmel_write16(priv->dev, DR, data); /* card is little-endian */
+ atmel_write16(priv->dev, DR, data >> 16);
+}
+
+
+/***************************************************************************/
+/* There follows the source form of the MAC address reading firmware */
+/***************************************************************************/
+#if 0
+
+/* Copyright 2003 Matthew T. Russotto */
+/* But derived from the Atmel 76C502 firmware written by Atmel and */
+/* included in "atmel wireless lan drivers" package */
+/**
+ This file is part of net.russotto.AtmelMACFW, hereto referred to
+ as AtmelMACFW
+
+ AtmelMACFW is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2
+ as published by the Free Software Foundation.
+
+ AtmelMACFW 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 AtmelMACFW; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+****************************************************************************/
+/* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E */
+/* It will probably work on the 76C504 and 76C502 RFMD_3COM */
+/* It only works on SPI EEPROM versions of the card. */
+
+/* This firmware initializes the SPI controller and clock, reads the MAC */
+/* address from the EEPROM into SRAM, and puts the SRAM offset of the MAC */
+/* address in MR2, and sets MR3 to 0x10 to indicate it is done */
+/* It also puts a complete copy of the EEPROM in SRAM with the offset in */
+/* MR4, for investigational purposes (maybe we can determine chip type */
+/* from that?) */
+
+ .org 0
+ .set MRBASE, 0x8000000
+ .set CPSR_INITIAL, 0xD3 /* IRQ/FIQ disabled, ARM mode, Supervisor state */
+ .set CPSR_USER, 0xD1 /* IRQ/FIQ disabled, ARM mode, USER state */
+ .set SRAM_BASE, 0x02000000
+ .set SP_BASE, 0x0F300000
+ .set UNK_BASE, 0x0F000000 /* Some internal device, but which one? */
+ .set SPI_CGEN_BASE, 0x0E000000 /* Some internal device, but which one? */
+ .set UNK3_BASE, 0x02014000 /* Some internal device, but which one? */
+ .set STACK_BASE, 0x5600
+ .set SP_SR, 0x10
+ .set SP_TDRE, 2 /* status register bit -- TDR empty */
+ .set SP_RDRF, 1 /* status register bit -- RDR full */
+ .set SP_SWRST, 0x80
+ .set SP_SPIEN, 0x1
+ .set SP_CR, 0 /* control register */
+ .set SP_MR, 4 /* mode register */
+ .set SP_RDR, 0x08 /* Read Data Register */
+ .set SP_TDR, 0x0C /* Transmit Data Register */
+ .set SP_CSR0, 0x30 /* chip select registers */
+ .set SP_CSR1, 0x34
+ .set SP_CSR2, 0x38
+ .set SP_CSR3, 0x3C
+ .set NVRAM_CMD_RDSR, 5 /* read status register */
+ .set NVRAM_CMD_READ, 3 /* read data */
+ .set NVRAM_SR_RDY, 1 /* RDY bit. This bit is inverted */
+ .set SPI_8CLOCKS, 0xFF /* Writing this to the TDR doesn't do anything to the
+ serial output, since SO is normally high. But it
+ does cause 8 clock cycles and thus 8 bits to be
+ clocked in to the chip. See Atmel's SPI
+ controller (e.g. AT91M55800) timing and 4K
+ SPI EEPROM manuals */
+
+ .set NVRAM_SCRATCH, 0x02000100 /* arbitrary area for scratchpad memory */
+ .set NVRAM_IMAGE, 0x02000200
+ .set NVRAM_LENGTH, 0x0200
+ .set MAC_ADDRESS_MIB, SRAM_BASE
+ .set MAC_ADDRESS_LENGTH, 6
+ .set MAC_BOOT_FLAG, 0x10
+ .set MR1, 0
+ .set MR2, 4
+ .set MR3, 8
+ .set MR4, 0xC
+RESET_VECTOR:
+ b RESET_HANDLER
+UNDEF_VECTOR:
+ b HALT1
+SWI_VECTOR:
+ b HALT1
+IABORT_VECTOR:
+ b HALT1
+DABORT_VECTOR:
+RESERVED_VECTOR:
+ b HALT1
+IRQ_VECTOR:
+ b HALT1
+FIQ_VECTOR:
+ b HALT1
+HALT1: b HALT1
+RESET_HANDLER:
+ mov r0, #CPSR_INITIAL
+ msr CPSR_c, r0 /* This is probably unnecessary */
+
+/* I'm guessing this is initializing clock generator electronics for SPI */
+ ldr r0, =SPI_CGEN_BASE
+ mov r1, #0
+ mov r1, r1, lsl #3
+ orr r1,r1, #0
+ str r1, [r0]
+ ldr r1, [r0, #28]
+ bic r1, r1, #16
+ str r1, [r0, #28]
+ mov r1, #1
+ str r1, [r0, #8]
+
+ ldr r0, =MRBASE
+ mov r1, #0
+ strh r1, [r0, #MR1]
+ strh r1, [r0, #MR2]
+ strh r1, [r0, #MR3]
+ strh r1, [r0, #MR4]
+
+ mov sp, #STACK_BASE
+ bl SP_INIT
+ mov r0, #10
+ bl DELAY9
+ bl GET_MAC_ADDR
+ bl GET_WHOLE_NVRAM
+ ldr r0, =MRBASE
+ ldr r1, =MAC_ADDRESS_MIB
+ strh r1, [r0, #MR2]
+ ldr r1, =NVRAM_IMAGE
+ strh r1, [r0, #MR4]
+ mov r1, #MAC_BOOT_FLAG
+ strh r1, [r0, #MR3]
+HALT2: b HALT2
+.func Get_Whole_NVRAM, GET_WHOLE_NVRAM
+GET_WHOLE_NVRAM:
+ stmdb sp!, {lr}
+ mov r2, #0 /* 0th bytes of NVRAM */
+ mov r3, #NVRAM_LENGTH
+ mov r1, #0 /* not used in routine */
+ ldr r0, =NVRAM_IMAGE
+ bl NVRAM_XFER
+ ldmia sp!, {lr}
+ bx lr
+.endfunc
+
+.func Get_MAC_Addr, GET_MAC_ADDR
+GET_MAC_ADDR:
+ stmdb sp!, {lr}
+ mov r2, #0x120 /* address of MAC Address within NVRAM */
+ mov r3, #MAC_ADDRESS_LENGTH
+ mov r1, #0 /* not used in routine */
+ ldr r0, =MAC_ADDRESS_MIB
+ bl NVRAM_XFER
+ ldmia sp!, {lr}
+ bx lr
+.endfunc
+.ltorg
+.func Delay9, DELAY9
+DELAY9:
+ adds r0, r0, r0, LSL #3 /* r0 = r0 * 9 */
+DELAYLOOP:
+ beq DELAY9_done
+ subs r0, r0, #1
+ b DELAYLOOP
+DELAY9_done:
+ bx lr
+.endfunc
+
+.func SP_Init, SP_INIT
+SP_INIT:
+ mov r1, #SP_SWRST
+ ldr r0, =SP_BASE
+ str r1, [r0, #SP_CR] /* reset the SPI */
+ mov r1, #0
+ str r1, [r0, #SP_CR] /* release SPI from reset state */
+ mov r1, #SP_SPIEN
+ str r1, [r0, #SP_MR] /* set the SPI to MASTER mode*/
+ str r1, [r0, #SP_CR] /* enable the SPI */
+
+/* My guess would be this turns on the SPI clock */
+ ldr r3, =SPI_CGEN_BASE
+ ldr r1, [r3, #28]
+ orr r1, r1, #0x2000
+ str r1, [r3, #28]
+
+ ldr r1, =0x2000c01
+ str r1, [r0, #SP_CSR0]
+ ldr r1, =0x2000201
+ str r1, [r0, #SP_CSR1]
+ str r1, [r0, #SP_CSR2]
+ str r1, [r0, #SP_CSR3]
+ ldr r1, [r0, #SP_SR]
+ ldr r0, [r0, #SP_RDR]
+ bx lr
+.endfunc
+.func NVRAM_Init, NVRAM_INIT
+NVRAM_INIT:
+ ldr r1, =SP_BASE
+ ldr r0, [r1, #SP_RDR]
+ mov r0, #NVRAM_CMD_RDSR
+ str r0, [r1, #SP_TDR]
+SP_loop1:
+ ldr r0, [r1, #SP_SR]
+ tst r0, #SP_TDRE
+ beq SP_loop1
+
+ mov r0, #SPI_8CLOCKS
+ str r0, [r1, #SP_TDR]
+SP_loop2:
+ ldr r0, [r1, #SP_SR]
+ tst r0, #SP_TDRE
+ beq SP_loop2
+
+ ldr r0, [r1, #SP_RDR]
+SP_loop3:
+ ldr r0, [r1, #SP_SR]
+ tst r0, #SP_RDRF
+ beq SP_loop3
+
+ ldr r0, [r1, #SP_RDR]
+ and r0, r0, #255
+ bx lr
+.endfunc
+
+.func NVRAM_Xfer, NVRAM_XFER
+ /* r0 = dest address */
+ /* r1 = not used */
+ /* r2 = src address within NVRAM */
+ /* r3 = length */
+NVRAM_XFER:
+ stmdb sp!, {r4, r5, lr}
+ mov r5, r0 /* save r0 (dest address) */
+ mov r4, r3 /* save r3 (length) */
+ mov r0, r2, LSR #5 /* SPI memories put A8 in the command field */
+ and r0, r0, #8
+ add r0, r0, #NVRAM_CMD_READ
+ ldr r1, =NVRAM_SCRATCH
+ strb r0, [r1, #0] /* save command in NVRAM_SCRATCH[0] */
+ strb r2, [r1, #1] /* save low byte of source address in NVRAM_SCRATCH[1] */
+_local1:
+ bl NVRAM_INIT
+ tst r0, #NVRAM_SR_RDY
+ bne _local1
+ mov r0, #20
+ bl DELAY9
+ mov r2, r4 /* length */
+ mov r1, r5 /* dest address */
+ mov r0, #2 /* bytes to transfer in command */
+ bl NVRAM_XFER2
+ ldmia sp!, {r4, r5, lr}
+ bx lr
+.endfunc
+
+.func NVRAM_Xfer2, NVRAM_XFER2
+NVRAM_XFER2:
+ stmdb sp!, {r4, r5, r6, lr}
+ ldr r4, =SP_BASE
+ mov r3, #0
+ cmp r0, #0
+ bls _local2
+ ldr r5, =NVRAM_SCRATCH
+_local4:
+ ldrb r6, [r5, r3]
+ str r6, [r4, #SP_TDR]
+_local3:
+ ldr r6, [r4, #SP_SR]
+ tst r6, #SP_TDRE
+ beq _local3
+ add r3, r3, #1
+ cmp r3, r0 /* r0 is # of bytes to send out (command+addr) */
+ blo _local4
+_local2:
+ mov r3, #SPI_8CLOCKS
+ str r3, [r4, #SP_TDR]
+ ldr r0, [r4, #SP_RDR]
+_local5:
+ ldr r0, [r4, #SP_SR]
+ tst r0, #SP_RDRF
+ beq _local5
+ ldr r0, [r4, #SP_RDR] /* what's this byte? It's the byte read while writing the TDR -- nonsense, because the NVRAM doesn't read and write at the same time */
+ mov r0, #0
+ cmp r2, #0 /* r2 is # of bytes to copy in */
+ bls _local6
+_local7:
+ ldr r5, [r4, #SP_SR]
+ tst r5, #SP_TDRE
+ beq _local7
+ str r3, [r4, #SP_TDR] /* r3 has SPI_8CLOCKS */
+_local8:
+ ldr r5, [r4, #SP_SR]
+ tst r5, #SP_RDRF
+ beq _local8
+ ldr r5, [r4, #SP_RDR] /* but didn't we read this byte above? */
+ strb r5, [r1], #1 /* postindexed */
+ add r0, r0, #1
+ cmp r0, r2
+ blo _local7 /* since we don't send another address, the NVRAM must be capable of sequential reads */
+_local6:
+ mov r0, #200
+ bl DELAY9
+ ldmia sp!, {r4, r5, r6, lr}
+ bx lr
+#endif
diff -urN linux-2.5.70-bk10/drivers/net/wireless/atmel_cs.c linux-2.5.70-bk11/drivers/net/wireless/atmel_cs.c
--- linux-2.5.70-bk10/drivers/net/wireless/atmel_cs.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.5.70-bk11/drivers/net/wireless/atmel_cs.c 2003-06-06 04:38:24.000000000 -0700
@@ -0,0 +1,768 @@
+/*** -*- linux-c -*- **********************************************************
+
+ Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+ Copyright 2000-2001 ATMEL Corporation.
+ Copyright 2003 Simon Kelley.
+
+ This code was developed from version 2.1.1 of the Atmel drivers,
+ released by Atmel corp. under the GPL in December 2002. It also
+ includes code from the Linux aironet drivers (C) Benjamin Reed,
+ and the Linux PCMCIA package, (C) David Hinds.
+
+ For all queries about this code, please contact the current author,
+ Simon Kelley and not Atmel Corporation.
+
+ 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+******************************************************************************/
+
+#include
+#ifdef __IN_PCMCIA_PACKAGE__
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+/*
+ All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
+ you do not define PCMCIA_DEBUG at all, all the debug code will be
+ left out. If you compile with PCMCIA_DEBUG=0, the debug code will
+ be present but disabled -- but it can then be enabled for specific
+ modules at load time with a 'pc_debug=#' option to insmod.
+*/
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+MODULE_PARM(pc_debug, "i");
+static char *version = "$Revision: 1.2 $";
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
+#else
+#define DEBUG(n, args...)
+#endif
+
+/*====================================================================*/
+
+/* Parameters that can be set with 'insmod' */
+
+/* The old way: bit map of interrupts to choose from */
+/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
+static u_int irq_mask = 0xdeb8;
+/* Newer, simpler way of listing specific interrupts */
+static int irq_list[4] = { -1 };
+
+MODULE_AUTHOR("Simon Kelley");
+MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethnet cards.");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+
+/*====================================================================*/
+
+/*
+ The event() function is this driver's Card Services event handler.
+ It will be called by Card Services when an appropriate card status
+ event is received. The config() and release() entry points are
+ used to configure or release a socket, in response to card
+ insertion and ejection events. They are invoked from the atmel_cs
+ event handler.
+*/
+
+struct net_device *init_atmel_card(int, int, char *, int, struct device *,
+ int (*present_func)(void *), void * );
+void stop_atmel_card( struct net_device *, int );
+int reset_atmel_card( struct net_device * );
+
+static void atmel_config(dev_link_t *link);
+static void atmel_release(u_long arg);
+static int atmel_event(event_t event, int priority,
+ event_callback_args_t *args);
+
+/*
+ The attach() and detach() entry points are used to create and destroy
+ "instances" of the driver, where each instance represents everything
+ needed to manage one actual PCMCIA card.
+*/
+
+static dev_link_t *atmel_attach(void);
+static void atmel_detach(dev_link_t *);
+
+/*
+ You'll also need to prototype all the functions that will actually
+ be used to talk to your device. See 'pcmem_cs' for a good example
+ of a fully self-sufficient driver; the other drivers rely more or
+ less on other parts of the kernel.
+*/
+
+/*
+ The dev_info variable is the "key" that is used to match up this
+ device driver with appropriate cards, through the card configuration
+ database.
+*/
+
+static dev_info_t dev_info = "atmel_cs";
+
+/*
+ A linked list of "instances" of the atmelnet device. Each actual
+ PCMCIA card corresponds to one device instance, and is described
+ by one dev_link_t structure (defined in ds.h).
+
+ You may not want to use a linked list for this -- for example, the
+ memory card driver uses an array of dev_link_t pointers, where minor
+ device numbers are used to derive the corresponding array index.
+*/
+
+static dev_link_t *dev_list = NULL;
+
+/*
+ A dev_link_t structure has fields for most things that are needed
+ to keep track of a socket, but there will usually be some device
+ specific information that also needs to be kept track of. The
+ 'priv' pointer in a dev_link_t structure can be used to point to
+ a device-specific private data structure, like this.
+
+ A driver needs to provide a dev_node_t structure for each device
+ on a card. In some cases, there is only one device per card (for
+ example, ethernet cards, modems). In other cases, there may be
+ many actual or logical devices (SCSI adapters, memory cards with
+ multiple partitions). The dev_node_t structures need to be kept
+ in a linked list starting at the 'dev' field of a dev_link_t
+ structure. We allocate them in the card's private data structure,
+ because they generally shouldn't be allocated dynamically.
+
+ In this case, we also provide a flag to indicate if a device is
+ "stopped" due to a power management event, or card ejection. The
+ device IO routines can use a flag like this to throttle IO to a
+ card that is not ready to accept it.
+*/
+
+typedef struct local_info_t {
+ dev_node_t node;
+ struct net_device *eth_dev;
+} local_info_t;
+
+/*======================================================================
+
+ This bit of code is used to avoid unregistering network devices
+ at inappropriate times. 2.2 and later kernels are fairly picky
+ about when this can happen.
+
+ ======================================================================*/
+
+static void flush_stale_links(void)
+{
+ dev_link_t *link, *next;
+ for (link = dev_list; link; link = next) {
+ next = link->next;
+ if (link->state & DEV_STALE_LINK)
+ atmel_detach(link);
+ }
+}
+
+/*======================================================================
+
+ atmel_attach() creates an "instance" of the driver, allocating
+ local data structures for one device. The device is registered
+ with Card Services.
+
+ The dev_link structure is initialized, but we don't actually
+ configure the card at this point -- we wait until we receive a
+ card insertion event.
+
+ ======================================================================*/
+
+static dev_link_t *atmel_attach(void)
+{
+ client_reg_t client_reg;
+ dev_link_t *link;
+ local_info_t *local;
+ int ret, i;
+
+ DEBUG(0, "atmel_attach()\n");
+ flush_stale_links();
+
+ /* Initialize the dev_link_t structure */
+ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+ if (!link) {
+ printk(KERN_ERR "atmel_cs: no memory for new device\n");
+ return NULL;
+ }
+ memset(link, 0, sizeof(struct dev_link_t));
+ init_timer(&link->release);
+ link->release.function = &atmel_release;
+ link->release.data = (u_long)link;
+
+ /* Interrupt setup */
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i = 0; i < 4; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+ link->irq.Handler = NULL;
+
+ /*
+ General socket configuration defaults can go here. In this
+ client, we assume very little, and rely on the CIS for almost
+ everything. In most clients, many details (i.e., number, sizes,
+ and attributes of IO windows) are fixed by the nature of the
+ device, and can be hard-wired here.
+ */
+ link->conf.Attributes = 0;
+ link->conf.Vcc = 50;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Allocate space for private device-specific data */
+ local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ if (!local) {
+ printk(KERN_ERR "atmel_cs: no memory for new device\n");
+ kfree (link);
+ return NULL;
+ }
+ memset(local, 0, sizeof(local_info_t));
+ link->priv = local;
+
+ /* Register with Card Services */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = &dev_info;
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &atmel_event;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+ ret = CardServices(RegisterClient, &link->handle, &client_reg);
+ if (ret != 0) {
+ cs_error(link->handle, RegisterClient, ret);
+ atmel_detach(link);
+ return NULL;
+ }
+
+ return link;
+} /* atmel_attach */
+
+/*======================================================================
+
+ This deletes a driver "instance". The device is de-registered
+ with Card Services. If it has been released, all local data
+ structures are freed. Otherwise, the structures will be freed
+ when the device is released.
+
+ ======================================================================*/
+
+static void atmel_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+
+ DEBUG(0, "atmel_detach(0x%p)\n", link);
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+ if (*linkp == link) break;
+ if (*linkp == NULL)
+ return;
+
+ del_timer(&link->release);
+ if ( link->state & DEV_CONFIG ) {
+ atmel_release( (int)link );
+ if ( link->state & DEV_STALE_CONFIG ) {
+ link->state |= DEV_STALE_LINK;
+ return;
+ }
+ }
+
+
+ /* Break the link with Card Services */
+ if (link->handle)
+ CardServices(DeregisterClient, link->handle);
+
+
+
+ /* Unlink device structure, free pieces */
+ *linkp = link->next;
+ if (link->priv) {
+ kfree(link->priv);
+ }
+ kfree(link);
+
+} /* atmel_detach */
+
+/*======================================================================
+
+ atmel_config() is scheduled to run after a CARD_INSERTION event
+ is received, to configure the PCMCIA socket, and to make the
+ device available to the system.
+
+ ======================================================================*/
+
+#define CS_CHECK(fn, args...) \
+while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
+
+#define CFG_CHECK(fn, args...) \
+if (CardServices(fn, args) != 0) goto next_entry
+
+/* Call-back function to interrogate PCMCIA-specific information
+ about the current existance of the card */
+static int card_present(void *arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+ if (link->state & DEV_SUSPEND)
+ return 0;
+ else if (link->state & DEV_PRESENT)
+ return 1;
+
+ return 0;
+}
+
+/* list of cards we know about and their firmware requirements.
+ Go either by Manfid or version strings.
+ Cards not in this list will need a firmware parameter to the module
+ in all probability. Note that the SMC 2632 V2 and V3 have the same
+ manfids, so we ignore those and use the version1 strings. */
+
+static struct {
+ int manf, card;
+ char *ver1;
+ char *firmware;
+ char *name;
+} card_table[] = {
+ { 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d.bin", "Actiontec 802CAT1" },
+ { 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502.bin", "NoName-RFMD" },
+ { 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d.bin", "NoName-revD" },
+ { 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e.bin", "NoName-revE" },
+ { 0, 0, "ATMEL/AT76C504", "atmel_at76c504.bin", "NoName-504" },
+ { MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com.bin", "3com 3CRWE62092B" },
+ { MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com.bin", "3com 3CRSHPW_96" },
+ { 0, 0, "SMC/2632W-V2", "atmel_at76c502.bin", "SMC 2632W-V2" },
+ { 0, 0, "SMC/2632W", "atmel_at76c502d.bin", "SMC 2632W-V3" },
+ { 0xd601, 0x0007, NULL, "atmel_at76c502.bin", "Sitecom WLAN-011"}, /* suspect - from a usenet posting. */
+ { 0x01bf, 0x3302, NULL, "atmel_at76c502d.bin", "Belkin F5D6060u"}, /* " " " " " */
+};
+
+/* This is strictly temporary, until PCMCIA devices get integrated into the device model. */
+static struct device atmel_device = {
+ .name = "Atmel at76c50x wireless",
+ .bus_id = "pcmcia",
+};
+
+static void atmel_config(dev_link_t *link)
+{
+ client_handle_t handle;
+ tuple_t tuple;
+ cisparse_t parse;
+ local_info_t *dev;
+ int last_fn, last_ret;
+ u_char buf[64];
+ int card_index = -1;
+
+ handle = link->handle;
+ dev = link->priv;
+
+ DEBUG(0, "atmel_config(0x%p)\n", link);
+
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+
+ tuple.DesiredTuple = CISTPL_MANFID;
+ if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
+ int i;
+ cistpl_manfid_t *manfid;
+ CS_CHECK(GetTupleData, handle, &tuple);
+ CS_CHECK(ParseTuple, handle, &tuple, &parse);
+ manfid = &(parse.manfid);
+ for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
+ if (!card_table[i].ver1 &&
+ manfid->manf == card_table[i].manf &&
+ manfid->card == card_table[i].card) {
+ card_index = i;
+ goto done;
+ }
+ }
+ }
+
+ tuple.DesiredTuple = CISTPL_VERS_1;
+ if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
+ int i, j, k;
+ cistpl_vers_1_t *ver1;
+ CS_CHECK(GetTupleData, handle, &tuple);
+ CS_CHECK(ParseTuple, handle, &tuple, &parse);
+ ver1 = &(parse.version_1);
+
+ for (i = 0; i < sizeof(card_table)/sizeof(card_table[0]); i++) {
+ for (j = 0; j < ver1->ns; j++) {
+ char *p = card_table[i].ver1;
+ char *q = &ver1->str[ver1->ofs[j]];
+ if (!p)
+ goto mismatch;
+ for (k = 0; k < j; k++) {
+ while ((*p != '\0') && (*p != '/')) p++;
+ if (*p == '\0')
+ goto mismatch;
+ p++;
+ }
+ while((*q != '\0') && (*p != '\0') &&
+ (*p != '/') && (*p == *q)) p++, q++;
+ if (((*p != '\0') && *p != '/') || *q != '\0')
+ goto mismatch;
+ }
+ card_index = i;
+ goto done;
+
+ mismatch:
+
+ }
+ done:
+ }
+
+ /*
+ This reads the card's CONFIG tuple to find its configuration
+ registers.
+ */
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ CS_CHECK(GetFirstTuple, handle, &tuple);
+ CS_CHECK(GetTupleData, handle, &tuple);
+ CS_CHECK(ParseTuple, handle, &tuple, &parse);
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+
+ /*
+ In this loop, we scan the CIS for configuration table entries,
+ each of which describes a valid card configuration, including
+ voltage, IO window, memory window, and interrupt settings.
+
+ We make no assumptions about the card to be configured: we use
+ just the information available in the CIS. In an ideal world,
+ this would work for any PCMCIA card, but it requires a complete
+ and accurate CIS. In practice, a driver usually "knows" most of
+ these things without consulting the CIS, and most client drivers
+ will only use the CIS to fill in implementation-defined details.
+ */
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, handle, &tuple);
+ while (1) {
+ cistpl_cftable_entry_t dflt = { 0 };
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ CFG_CHECK(GetTupleData, handle, &tuple);
+ CFG_CHECK(ParseTuple, handle, &tuple, &parse);
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
+ if (cfg->index == 0) goto next_entry;
+ link->conf.ConfigIndex = cfg->index;
+
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ link->conf.Attributes |= CONF_ENABLE_SPKR;
+ link->conf.Status = CCSR_AUDIO_ENA;
+ }
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt.vcc.present & (1<conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
+
+ if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+ /* Do we need to allocate an interrupt? */
+ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ if (!(io->flags & CISTPL_IO_8BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.BasePort1 = io->win[0].base;
+ link->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ link->io.Attributes2 = link->io.Attributes1;
+ link->io.BasePort2 = io->win[1].base;
+ link->io.NumPorts2 = io->win[1].len;
+ }
+ }
+
+ /* This reserves IO space but doesn't actually enable it */
+ CFG_CHECK(RequestIO, link->handle, &link->io);
+ /* If we got this far, we're cool! */
+ break;
+
+ next_entry:
+ CS_CHECK(GetNextTuple, handle, &tuple);
+ }
+
+ /*
+ Allocate an interrupt line. Note that this does not assign a
+ handler to the interrupt, unless the 'Handler' member of the
+ irq structure is initialized.
+ */
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ CS_CHECK(RequestIRQ, link->handle, &link->irq);
+
+ /*
+ This actually configures the PCMCIA socket -- setting up
+ the I/O windows and the interrupt mapping, and putting the
+ card and host interface into "Memory and IO" mode.
+ */
+ CS_CHECK(RequestConfiguration, link->handle, &link->conf);
+
+ if (link->irq.AssignedIRQ == 0) {
+ printk(KERN_ALERT
+ "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
+ goto cs_failed;
+ }
+
+ ((local_info_t*)link->priv)->eth_dev =
+ init_atmel_card(link->irq.AssignedIRQ,
+ link->io.BasePort1,
+ card_index == -1 ? NULL : card_table[card_index].firmware,
+ card_index == -1 ? 0 : (card_table[card_index].manf == MANFID_3COM),
+ &atmel_device,
+ card_present,
+ link);
+ if (!((local_info_t*)link->priv)->eth_dev)
+ goto cs_failed;
+
+ /*
+ At this point, the dev_node_t structure(s) need to be
+ initialized and arranged in a linked list at link->dev.
+ */
+ strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
+ dev->node.major = dev->node.minor = 0;
+ link->dev = &dev->node;
+
+ /* Finally, report what we've done */
+ printk(KERN_INFO "%s: %s%sindex 0x%02x: Vcc %d.%d",
+ dev->node.dev_name,
+ card_index == -1 ? "" : card_table[card_index].name,
+ card_index == -1 ? "" : " ",
+ link->conf.ConfigIndex,
+ link->conf.Vcc/10, link->conf.Vcc%10);
+ if (link->conf.Vpp1)
+ printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ printk(", irq %d", link->irq.AssignedIRQ);
+ if (link->io.NumPorts1)
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+ link->io.BasePort1+link->io.NumPorts1-1);
+ if (link->io.NumPorts2)
+ printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+ link->io.BasePort2+link->io.NumPorts2-1);
+ printk("\n");
+
+ link->state &= ~DEV_CONFIG_PENDING;
+ return;
+
+ cs_failed:
+ cs_error(link->handle, last_fn, last_ret);
+ atmel_release((u_long)link);
+
+} /* atmel_config */
+
+/*======================================================================
+
+ After a card is removed, atmel_release() will unregister the
+ device, and release the PCMCIA configuration. If the device is
+ still open, this will be postponed until it is closed.
+
+ ======================================================================*/
+
+static void atmel_release(u_long arg)
+{
+ dev_link_t *link = (dev_link_t *)arg;
+ struct net_device *dev = ((local_info_t*)link->priv)->eth_dev;
+
+ DEBUG(0, "atmel_release(0x%p)\n", link);
+
+ /* Unlink the device chain */
+ link->dev = NULL;
+
+ if (dev)
+ stop_atmel_card(dev, 0);
+ ((local_info_t*)link->priv)->eth_dev = 0;
+
+ /* Don't bother checking to see if these succeed or not */
+ CardServices(ReleaseConfiguration, link->handle);
+ if (link->io.NumPorts1)
+ CardServices(ReleaseIO, link->handle, &link->io);
+ if (link->irq.AssignedIRQ)
+ CardServices(ReleaseIRQ, link->handle, &link->irq);
+ link->state &= ~DEV_CONFIG;
+
+} /* atmel_release */
+
+/*======================================================================
+
+ The card status event handler. Mostly, this schedules other
+ stuff to run after an event is received.
+
+ When a CARD_REMOVAL event is received, we immediately set a
+ private flag to block future accesses to this device. All the
+ functions that actually access the device should check this flag
+ to make sure the card is still present.
+
+ ======================================================================*/
+
+static int atmel_event(event_t event, int priority,
+ event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+ local_info_t *local = link->priv;
+
+ DEBUG(1, "atmel_event(0x%06x)\n", event);
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(local->eth_dev);
+ mod_timer(&link->release, jiffies + HZ/20);
+ }
+ break;
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ atmel_config(link);
+ break;
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(local->eth_dev);
+ CardServices(ReleaseConfiguration, link->handle);
+ }
+ break;
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG) {
+ CardServices(RequestConfiguration, link->handle, &link->conf);
+ reset_atmel_card(local->eth_dev);
+ netif_device_attach(local->eth_dev);
+ }
+ break;
+ }
+ return 0;
+} /* atmel_event */
+
+/*====================================================================*/
+static struct pcmcia_driver atmel_driver = {
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = "atmel_cs",
+ },
+ .attach = atmel_attach,
+ .detach = atmel_detach,
+};
+
+static int atmel_cs_init(void)
+{
+ return pcmcia_register_driver(&atmel_driver);
+}
+
+static void atmel_cs_cleanup(void)
+{
+ pcmcia_unregister_driver(&atmel_driver);
+
+ /* XXX: this really needs to move into generic code.. */
+ while (dev_list != NULL) {
+ if (dev_list->state & DEV_CONFIG)
+ atmel_release((u_long)dev_list);
+ atmel_detach(dev_list);
+ }
+}
+
+/*
+ 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.
+
+ In addition:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+module_init(atmel_cs_init);
+module_exit(atmel_cs_cleanup);
diff -urN linux-2.5.70-bk10/drivers/pci/pci.h linux-2.5.70-bk11/drivers/pci/pci.h
--- linux-2.5.70-bk10/drivers/pci/pci.h 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/pci/pci.h 2003-06-06 04:38:24.000000000 -0700
@@ -25,7 +25,6 @@
/* Functions for PCI Hotplug drivers to use */
extern struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
-extern void pci_remove_bus_device(struct pci_dev *dev);
extern int pci_remove_device_safe(struct pci_dev *dev);
extern unsigned char pci_max_busnr(void);
extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
diff -urN linux-2.5.70-bk10/drivers/pci/pci.ids linux-2.5.70-bk11/drivers/pci/pci.ids
--- linux-2.5.70-bk10/drivers/pci/pci.ids 2003-05-26 18:00:40.000000000 -0700
+++ linux-2.5.70-bk11/drivers/pci/pci.ids 2003-06-06 04:38:24.000000000 -0700
@@ -3745,19 +3745,26 @@
11fc Silicon Magic
11fd High Street Consultants
11fe Comtrol Corporation
- 0001 RocketPort 8 Oct
- 0002 RocketPort 8 Intf
- 0003 RocketPort 16 Intf
- 0004 RocketPort 32 Intf
- 0005 RocketPort Octacable
- 0006 RocketPort 8J
- 0007 RocketPort 4-port
- 0008 RocketPort 8-port
- 0009 RocketPort 16-port
- 000a RocketPort Plus Quadcable
- 000b RocketPort Plus Octacable
- 000c RocketPort 8-port Modem
- 8015 RocketPort 4-port UART 16954
+ 0001 Rocketport 32 port w/external I/F
+ 0002 Rocketport 8 port w/external I/F
+ 0003 Rocketport 16 port w/external I/F
+ 0004 Rocketport 4 port w/quad cable
+ 0005 Rocketport 8 port w/octa cable
+ 0006 Rocketport 8 port w/RJ11 connectors
+ 0007 Rocketport 4 port w/RJ11 connectors
+ 000a Rocketport Plus 4 port
+ 000b Rocketport Plus 8 port
+ 000c RocketModem 6 port
+ 000d RocketModem 4-port
+ 000e Rocketport Plus 2 port RS232
+ 000f Rocketport Plus 2 port RS422
+ 0801 Rocketport UPCI 32 port w/external I/F
+ 0802 Rocketport UPCI 8 port w/external I/F
+ 0803 Rocketport UPCI 16 port w/external I/F
+ 0805 Rocketport UPCI 8 port w/octa cable
+ 080C RocketModem III 8 port
+ 080D RocketModem III 4 port
+ 0903 Rocketport Compact PCI 16 port w/external I/F
11ff Scion Corporation
1200 CSS Corporation
1201 Vista Controls Corp
diff -urN linux-2.5.70-bk10/drivers/pci/probe.c linux-2.5.70-bk11/drivers/pci/probe.c
--- linux-2.5.70-bk10/drivers/pci/probe.c 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/pci/probe.c 2003-06-06 04:38:24.000000000 -0700
@@ -689,7 +689,6 @@
}
EXPORT_SYMBOL(pci_scan_bus_parented);
-EXPORT_SYMBOL(pci_devices);
EXPORT_SYMBOL(pci_root_buses);
#ifdef CONFIG_HOTPLUG
diff -urN linux-2.5.70-bk10/drivers/pci/search.c linux-2.5.70-bk11/drivers/pci/search.c
--- linux-2.5.70-bk10/drivers/pci/search.c 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/pci/search.c 2003-06-06 04:38:25.000000000 -0700
@@ -118,6 +118,34 @@
/**
+ * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id
+ * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
+ * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
+ * @from: Previous PCI device found in search, or %NULL for new search.
+ *
+ * Iterates through the list of known PCI devices in the reverse order of pci_find_device().
+ * If a PCI device is found with a matching @vendor and @device, a pointer to
+ * its device structure is returned. Otherwise, %NULL is returned.
+ * A new search is initiated by passing %NULL to the @from argument.
+ * Otherwise if @from is not %NULL, searches continue from previous device on the global list.
+ */
+struct pci_dev *
+pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
+{
+ struct list_head *n = from ? from->global_list.prev : pci_devices.prev;
+
+ while (n != &pci_devices) {
+ struct pci_dev *dev = pci_dev_g(n);
+ if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
+ (device == PCI_ANY_ID || dev->device == device))
+ return dev;
+ n = n->prev;
+ }
+ return NULL;
+}
+
+
+/**
* pci_find_class - begin or continue searching for a PCI device by class
* @class: search for a PCI device with this class designation
* @from: Previous PCI device found in search, or %NULL for new search.
@@ -143,8 +171,20 @@
return NULL;
}
+/**
+ * pci_present - determine if there are any pci devices on this system
+ *
+ * Returns 0 if no pci devices are present, 1 if pci devices are present.
+ */
+int pci_present(void)
+{
+ return !list_empty(&pci_devices);
+}
+
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_class);
EXPORT_SYMBOL(pci_find_device);
+EXPORT_SYMBOL(pci_find_device_reverse);
EXPORT_SYMBOL(pci_find_slot);
EXPORT_SYMBOL(pci_find_subsys);
+EXPORT_SYMBOL(pci_present);
diff -urN linux-2.5.70-bk10/drivers/scsi/Kconfig linux-2.5.70-bk11/drivers/scsi/Kconfig
--- linux-2.5.70-bk10/drivers/scsi/Kconfig 2003-05-26 18:00:57.000000000 -0700
+++ linux-2.5.70-bk11/drivers/scsi/Kconfig 2003-06-06 04:38:25.000000000 -0700
@@ -1559,7 +1559,7 @@
config SCSI_MESH
tristate "MESH (Power Mac internal SCSI) support"
- depends on ALL_PPC && SCSI
+ depends on PPC_PMAC && SCSI
help
Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
@@ -1590,7 +1590,7 @@
config SCSI_MAC53C94
tristate "53C94 (Power Mac external SCSI) support"
- depends on ALL_PPC && SCSI
+ depends on PPC_PMAC && SCSI
help
On Power Macintoshes (and clones) with two SCSI buses, the external
SCSI bus is usually controlled by a 53C94 SCSI bus adaptor. Older
diff -urN linux-2.5.70-bk10/drivers/serial/sunsab.c linux-2.5.70-bk11/drivers/serial/sunsab.c
--- linux-2.5.70-bk10/drivers/serial/sunsab.c 2003-05-26 18:00:38.000000000 -0700
+++ linux-2.5.70-bk11/drivers/serial/sunsab.c 2003-06-06 04:38:26.000000000 -0700
@@ -231,8 +231,10 @@
set_bit(SAB82532_ALLS, &up->irqflags);
}
+#if 0 /* bde@nwlink.com says this check causes problems */
if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR))
return;
+#endif
if (!(readb(&up->regs->r.star) & SAB82532_STAR_XFW))
return;
@@ -242,6 +244,7 @@
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
up->interrupt_mask1 |= SAB82532_IMR1_XPR;
writeb(up->interrupt_mask1, &up->regs->w.imr1);
+ uart_write_wakeup(&up->port);
return;
}
diff -urN linux-2.5.70-bk10/drivers/usb/image/hpusbscsi.c linux-2.5.70-bk11/drivers/usb/image/hpusbscsi.c
--- linux-2.5.70-bk10/drivers/usb/image/hpusbscsi.c 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/usb/image/hpusbscsi.c 2003-06-06 04:38:26.000000000 -0700
@@ -93,17 +93,6 @@
}
}
- /* USB initialisation magic for the simple case */
- result = usb_set_interface(dev, altsetting->desc.bInterfaceNumber, 0);
- switch (result) {
- case 0: /* no error */
- break;
- default:
- printk(KERN_ERR "unknown error %d from usb_set_interface\n",
- result);
- goto out_free_controlurb;
- }
-
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb(new->controlurb, new->dev,
usb_rcvintpipe(new->dev, new->ep_int),
diff -urN linux-2.5.70-bk10/drivers/usb/input/hid-input.c linux-2.5.70-bk11/drivers/usb/input/hid-input.c
--- linux-2.5.70-bk10/drivers/usb/input/hid-input.c 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/usb/input/hid-input.c 2003-06-06 04:38:26.000000000 -0700
@@ -70,8 +70,11 @@
hidinput = list_entry(lh, struct hid_input, list);
- for (i = 0; i < hidinput->maxfield; i++)
- if (hidinput->fields[i] == field)
+ if (! hidinput->report)
+ continue;
+
+ for (i = 0; i < hidinput->report->maxfield; i++)
+ if (hidinput->report->field[i] == field)
return &hidinput->input;
}
@@ -527,7 +530,7 @@
struct hid_report *report;
struct list_head *list;
struct hid_input *hidinput = NULL;
- int i, j;
+ int i, j, k;
INIT_LIST_HEAD(&hid->inputs);
@@ -539,57 +542,57 @@
if (i == hid->maxcollection)
return -1;
- report_enum = hid->report_enum + HID_INPUT_REPORT;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+ report_enum = hid->report_enum + k;
+ list = report_enum->report_list.next;
+ while (list != &report_enum->report_list) {
+ report = (struct hid_report *) list;
- if (!report->maxfield)
- continue;
+ if (!report->maxfield)
+ continue;
- if (!hidinput) {
- hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
if (!hidinput) {
- err("Out of memory during hid input probe");
- return -1;
- }
- memset(hidinput, 0, sizeof(*hidinput));
-
- list_add_tail(&hidinput->list, &hid->inputs);
+ hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
+ if (!hidinput) {
+ err("Out of memory during hid input probe");
+ return -1;
+ }
+ memset(hidinput, 0, sizeof(*hidinput));
- hidinput->input.private = hid;
- hidinput->input.event = hidinput_input_event;
- hidinput->input.open = hidinput_open;
- hidinput->input.close = hidinput_close;
-
- hidinput->input.name = hid->name;
- hidinput->input.phys = hid->phys;
- hidinput->input.uniq = hid->uniq;
- hidinput->input.id.bustype = BUS_USB;
- hidinput->input.id.vendor = dev->descriptor.idVendor;
- hidinput->input.id.product = dev->descriptor.idProduct;
- hidinput->input.id.version = dev->descriptor.bcdDevice;
- }
+ list_add_tail(&hidinput->list, &hid->inputs);
- for (i = 0; i < report->maxfield; i++)
- for (j = 0; j < report->field[i]->maxusage; j++)
- hidinput_configure_usage(hidinput, report->field[i],
- report->field[i]->usage + j);
-
- if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
- /* This will leave hidinput NULL, so that it
- * allocates another one if we have more inputs on
- * the same interface. Some devices (e.g. Happ's
- * UGCI) cram a lot of unrelated inputs into the
- * same interface. */
- hidinput->fields = report->field;
- hidinput->maxfield = report->maxfield;
+ hidinput->input.private = hid;
+ hidinput->input.event = hidinput_input_event;
+ hidinput->input.open = hidinput_open;
+ hidinput->input.close = hidinput_close;
+
+ hidinput->input.name = hid->name;
+ hidinput->input.phys = hid->phys;
+ hidinput->input.uniq = hid->uniq;
+ hidinput->input.id.bustype = BUS_USB;
+ hidinput->input.id.vendor = dev->descriptor.idVendor;
+ hidinput->input.id.product = dev->descriptor.idProduct;
+ hidinput->input.id.version = dev->descriptor.bcdDevice;
+ }
+
+ for (i = 0; i < report->maxfield; i++)
+ for (j = 0; j < report->field[i]->maxusage; j++)
+ hidinput_configure_usage(hidinput, report->field[i],
+ report->field[i]->usage + j);
+
+ if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
+ /* This will leave hidinput NULL, so that it
+ * allocates another one if we have more inputs on
+ * the same interface. Some devices (e.g. Happ's
+ * UGCI) cram a lot of unrelated inputs into the
+ * same interface. */
+ hidinput->report = report;
+ input_register_device(&hidinput->input);
+ hidinput = NULL;
+ }
- input_register_device(&hidinput->input);
- hidinput = NULL;
+ list = list->next;
}
-
- list = list->next;
}
/* This only gets called when we are a single-input (most of the
diff -urN linux-2.5.70-bk10/drivers/usb/input/hid.h linux-2.5.70-bk11/drivers/usb/input/hid.h
--- linux-2.5.70-bk10/drivers/usb/input/hid.h 2003-06-06 04:38:14.000000000 -0700
+++ linux-2.5.70-bk11/drivers/usb/input/hid.h 2003-06-06 04:38:26.000000000 -0700
@@ -324,8 +324,7 @@
struct hid_input {
struct list_head list;
- struct hid_field **fields;
- int maxfield;
+ struct hid_report *report;
struct input_dev input;
};
diff -urN linux-2.5.70-bk10/drivers/usb/serial/empeg.c linux-2.5.70-bk11/drivers/usb/serial/empeg.c
--- linux-2.5.70-bk10/drivers/usb/serial/empeg.c 2003-06-06 04:38:15.000000000 -0700
+++ linux-2.5.70-bk11/drivers/usb/serial/empeg.c 2003-06-06 04:38:27.000000000 -0700
@@ -460,14 +460,15 @@
static int empeg_startup (struct usb_serial *serial)
{
+ int r;
dbg("%s", __FUNCTION__);
dbg("%s - Set config to 1", __FUNCTION__);
- usb_set_configuration (serial->dev, 1);
+ r = usb_set_configuration (serial->dev, 1);
/* continue on with initialization */
- return 0;
+ return r;
}
diff -urN linux-2.5.70-bk10/drivers/video/Kconfig linux-2.5.70-bk11/drivers/video/Kconfig
--- linux-2.5.70-bk10/drivers/video/Kconfig 2003-05-26 18:00:21.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/Kconfig 2003-06-06 04:38:28.000000000 -0700
@@ -235,28 +235,28 @@
config FB_OF
bool "Open Firmware frame buffer device support"
- depends on FB && (PPC64 || (PPC && ALL_PPC))
+ depends on FB && (PPC64 || PPC_OF)
help
Say Y if you want support with Open Firmware for your graphics
board.
config FB_CONTROL
bool "Apple \"control\" display support"
- depends on FB && PPC && ALL_PPC
+ depends on FB && PPC_PMAC
help
This driver supports a frame buffer for the graphics adapter in the
Power Macintosh 7300 and others.
config FB_PLATINUM
bool "Apple \"platinum\" display support"
- depends on FB && PPC && ALL_PPC
+ depends on FB && PPC_PMAC
help
This driver supports a frame buffer for the "platinum" graphics
adapter in some Power Macintoshes.
config FB_VALKYRIE
bool "Apple \"valkyrie\" display support"
- depends on FB && (MAC || PPC && ALL_PPC)
+ depends on FB && (MAC || PPC_PMAC)
help
This driver supports a frame buffer for the "valkyrie" graphics
adapter in some Power Macintoshes.
diff -urN linux-2.5.70-bk10/drivers/video/aty/aty128fb.c linux-2.5.70-bk11/drivers/video/aty/aty128fb.c
--- linux-2.5.70-bk10/drivers/video/aty/aty128fb.c 2003-05-26 18:00:39.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/aty/aty128fb.c 2003-06-06 04:38:28.000000000 -0700
@@ -59,7 +59,7 @@
#include
#include
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
#include
#include
#include "../macmodes.h"
@@ -93,7 +93,7 @@
#define DBG(fmt, args...)
#endif
-#ifndef CONFIG_ALL_PPC
+#ifndef CONFIG_PPC_PMAC
/* default mode */
static struct fb_var_screeninfo default_var __initdata = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
@@ -103,7 +103,7 @@
0, FB_VMODE_NONINTERLACED
};
-#else /* CONFIG_ALL_PPC */
+#else /* CONFIG_PPC_PMAC */
/* default to 1024x768 at 75Hz on PPC - this will work
* on the iMac, the usual 640x480 @ 60Hz doesn't. */
static struct fb_var_screeninfo default_var = {
@@ -114,7 +114,7 @@
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
FB_VMODE_NONINTERLACED
};
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
/* default modedb mode */
/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
@@ -259,7 +259,7 @@
static char *mode_option __initdata = NULL;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
static int default_vmode __initdata = VMODE_1024_768_60;
static int default_cmode __initdata = CMODE_8;
#endif
@@ -1434,7 +1434,7 @@
continue;
}
#endif
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
/* vmode and cmode deprecated */
if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
@@ -1459,7 +1459,7 @@
}
continue;
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
mode_option = this_opt;
}
return 0;
@@ -1543,7 +1543,7 @@
#endif
var = default_var;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
if (_machine == _MACH_Pmac) {
if (mode_option) {
if (!mac_find_mode(&var, info, mode_option, 8))
@@ -1582,7 +1582,7 @@
var = default_var;
}
} else
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
{
if (fb_find_mode(&var, info, mode_option, NULL, 0,
&defaultmode, 8) == 0)
@@ -1872,7 +1872,7 @@
static void __init
aty128_timings(struct aty128fb_par *par)
{
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
/* instead of a table lookup, assume OF has properly
* setup the PLL registers and use their values
* to set the XCLK values and reference divider values */
@@ -1886,7 +1886,7 @@
if (!par->constants.dotclock)
par->constants.dotclock = 2950;
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
diff -urN linux-2.5.70-bk10/drivers/video/cirrusfb.c linux-2.5.70-bk11/drivers/video/cirrusfb.c
--- linux-2.5.70-bk10/drivers/video/cirrusfb.c 2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/cirrusfb.c 2003-06-06 04:38:28.000000000 -0700
@@ -56,7 +56,7 @@
#ifdef CONFIG_AMIGA
#include
#endif
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PREP
#include
#define isPReP (_machine == _MACH_prep)
#else
@@ -2395,7 +2395,7 @@
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PREP
#define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
#define PREP_IO_BASE ((volatile unsigned char *) 0x80000000)
static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
@@ -2408,7 +2408,7 @@
DPRINTK ("EXIT\n");
}
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PREP */
@@ -2543,7 +2543,7 @@
pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0,
0x00000000);
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PREP
get_prep_addrs (&board_addr, &info->fbregs_phys);
#endif
} else {
diff -urN linux-2.5.70-bk10/drivers/video/fbmon.c linux-2.5.70-bk11/drivers/video/fbmon.c
--- linux-2.5.70-bk10/drivers/video/fbmon.c 2003-05-26 18:00:56.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/fbmon.c 2003-06-06 04:38:28.000000000 -0700
@@ -29,7 +29,7 @@
#include
#include
#include
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
#include
#include
#endif
@@ -828,7 +828,7 @@
printk("========================================\n");
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
char *get_EDID_from_OF(struct pci_dev *pdev)
{
static char *propnames[] =
@@ -1256,7 +1256,7 @@
#ifdef CONFIG_X86
EXPORT_SYMBOL(get_EDID_from_BIOS);
#endif
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_OF
EXPORT_SYMBOL(get_EDID_from_OF);
#endif
EXPORT_SYMBOL(fb_get_monitor_limits);
diff -urN linux-2.5.70-bk10/drivers/video/matrox/matroxfb_base.c linux-2.5.70-bk11/drivers/video/matrox/matroxfb_base.c
--- linux-2.5.70-bk10/drivers/video/matrox/matroxfb_base.c 2003-06-06 04:38:15.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/matrox/matroxfb_base.c 2003-06-06 04:38:28.000000000 -0700
@@ -115,7 +115,7 @@
#include
#include
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
unsigned char nvram_read_byte(int);
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
@@ -1763,7 +1763,7 @@
}
/* FIXME: Where to move this?! */
-#if defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_PPC_PMAC)
#ifndef MODULE
if (_machine == _MACH_Pmac) {
struct fb_var_screeninfo var;
@@ -1783,7 +1783,7 @@
}
}
#endif /* !MODULE */
-#endif /* CONFIG_ALL_PPC */
+#endif /* CONFIG_PPC_PMAC */
vesafb_defined.xres_virtual = vesafb_defined.xres;
if (nopan) {
vesafb_defined.yres_virtual = vesafb_defined.yres;
@@ -2270,7 +2270,7 @@
dfp_type = simple_strtoul(this_opt+4, NULL, 0);
dfp = 1;
}
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
@@ -2441,7 +2441,7 @@
MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
MODULE_PARM(dfp_type, "i");
MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_PPC_PMAC
MODULE_PARM(vmode, "i");
MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
MODULE_PARM(cmode, "i");
diff -urN linux-2.5.70-bk10/drivers/video/matrox/matroxfb_base.h linux-2.5.70-bk11/drivers/video/matrox/matroxfb_base.h
--- linux-2.5.70-bk10/drivers/video/matrox/matroxfb_base.h 2003-06-06 04:38:15.000000000 -0700
+++ linux-2.5.70-bk11/drivers/video/matrox/matroxfb_base.h 2003-06-06 04:38:28.000000000 -0700
@@ -52,7 +52,7 @@
#include "../console/fbcon.h"
-#if defined(CONFIG_ALL_PPC)
+#if defined(CONFIG_PPC_PMAC)
#include
#include
#include