Powertweak
==========
-The 0.1.2 release:
-http://linux.powertweak.com/files/powertweak-0.1.2.tgz
-ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/powertweak/powertweak-0.1.2.tgz
+The 0.1.13 release:
+http://linux.powertweak.com/files/powertweak-0.1.13.tgz
+ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/powertweak/powertweak-0.1.13.tgz
Xosview
=======
Say Y here if you want to connect this type of still camera to
your computer's USB port. This driver can be used with gphoto 0.4.3
and higher (look at http://www.gphoto.org ).
- To use it create a device node with "mknod /dev/mustek c 10 171" and
+ To use it create a device node with "mknod /dev/mustek c 180 32" and
configure it in your software.
This code is also available as a module ( = code which can be
damaged. Also, make sure to run chkdsk from within Microsoft
Windows NT after having performed any writes to a NTFS partition
from Linux to detect any problems as early as possible.
+ Please note that write support is limited to Windows NT4 and
+ earlier versions.
If unsure, say N.
sets should work as well - if the md driver can be talked into
using the same layout as Windows NT.
+Please note that the experimental write support is limited to
+Windows NT4 and earlier versions.
+
The ntfs driver supports the following mount options:
iocharset=name Character set to use when returning file names.
Unlike VFAT, NTFS suppresses names that contain
+Documentation/networking/vortex.txt
+Andrew Morton <andrewm@uow.edu.au>
+30 April 2000
+
+
This document describes the usage and errata of the 3Com "Vortex" device
-driver for Linux.
+driver for Linux, 3c59x.c.
The driver was written by Donald Becker <becker@cesdis.gsfc.nasa.gov>
Andrew Morton <andrewm@uow.edu.au>
Netdev mailing list <netdev@oss.sgi.com>
+ Linux kernel mailing list <linux-kernel@vger.rutgers.edu>
+
+Please note the 'Reporting and Diagnosing Problems' section at the end
+of this file.
+
+Since kernel 2.3.99-pre6, this driver incorporates the support for the
+3c575-series Cardbus cards which used to be handled by 3c575_cb.c.
This driver supports the following hardware:
3c450 Cyclone/unknown
3Com Boomerang (unknown version)
-When loaded as a module the following variables may be set:
- name type description
- debug int The debug message level, 0 (no messages) to 6 (wordy).
- options int[] The media type override and card operation settings
- (See list below.)
-An example of loading the vortex module is
- insmod 3c59x.o debug=1 options=0,,12
-This sets the debug message level to minimal messages, sets the first card to
-the 10baseT transceiver, the second to the EEPROM-set transceiver, and the
-third card to operate in full-duplex mode using its 100baseTx transceiver.
-(Note: card ordering is set by the PCI BIOS.)
+Module parameters
+=================
+
+There are several parameters which may be provided to the driver when
+its module is loaded. These are usually placed in /etc/modules.conf
+(used to be conf.modules). Example:
+
+options 3c59x debug=3 rx_copybreak=300
+
+If you are using the PCMCIA tools (cardmgr) then theoptions may be
+placed in /etc/pcmcia/config.opts:
+
+module "3c59x" opts "debug=3 extra_reset=1"
+
+
+The supported parameters are:
+
+debug=N
+
+ Where N is a number from 0 to 7. Anything above 3 produces a lot
+ of output in your system logs. debug=1 is default.
+
+options=N1,N2,N3,...
+
+ Each number in the list provides an option to the corresponding
+ network card. So if you have two 3c905's and you wish to provide
+ them with option 0x204 you would use:
-Possible media type settings
+ options=0x204,0x204
+
+ The individual options are composed of a number of bitfields which
+ have the following meanings:
+
+ ssible media type settings
0 10baseT
1 10Mbs AUI
2 undefined
3 10base2 (BNC)
4 100base-TX
5 100base-FX
- 6 MII (not yet available)
- 7 <Use default setting>
-
- 8 Full-duplex bit
- 8 10baseT full-duplex
- 12 100baseTx full-duplex
- 16 Bus-master enable bit (experimental use only!)
+ 6 MII (Media Independent Interface)
+ 7 Use default setting from EEPROM
+ 8 Autonegotiate
+ 9 External MII
+ 10 Use default setting from EEPROM
-Details of the device driver implementation are at the top of the source file.
+ When generating a value for the 'options' setting, the above media
+ selection values may be OR'ed (or added to) the following:
-Additional documentation is available at Don Becker's Linux Drivers site:
+ 512 (0x200) Force full-duplex
+ 16 (0x10) Bus-master enable bit (Old Vortex cards only)
+
+ For example:
+
+ insmod 3c59x options=0x204
+
+ will force full-duplex 100base-TX, rather than allowing the usual
+ autonegotiation.
+
+full_duplex=N1,N2,N3...
+
+ Similar to bit 9 of 'options'. Forces the corresponding card into
+ full-duplex mode.
+
+rx_copybreak=M
+
+ The driver preallocates 32 full-sized (1536 byte) network buffers
+ for receiving. When a packet arrives, the driver has to decide
+ whether to leave the packet in its full-sized buffer, or to allocate
+ a smaller buffer and copy the packet across into it.
+
+ This is a speed/space tradeoff.
+
+ The value of rx_copybreak is used to decide when to make the copy.
+ If the packet size is less than rx_copybreak, the packet is copied.
+ The default value for rx_copybreak is 200 bytes.
+
+max_interrupt_work=N
+
+ The driver's interrupt service routine can handle many receive and
+ transmit packets in a single invokation. It does this in a loop.
+ The value of max_interrupt_work governs how mnay times the interrupt
+ service routine will loop. The default value is 32 loops. If this
+ is exceeded the interrupt service routine gives up and generates a
+ warning message "eth0: Too much work in interrupt".
+
+extra_reset=N
+
+ Where N is 0 or 1 (default 0).
+
+ Some network cards (notably 3CCFE575CT Cardbus) do not initialise
+ correctly and need an extra transmitter reset. If you find that the
+ card comes up receiving but not transmitting, try giving the module
+ the 'extra_reset=1' option.
+
+compaq_ioaddr=N
+compaq_irq=N
+compaq_device_id=N
+
+ "Variables to work-around the Compaq PCI BIOS32 problem"....
- http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html
Additional resources
--------------------
+Details of the device driver implementation are at the top of the source file.
+
+Additional documentation is available at Don Becker's Linux Drivers site:
+
+ http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html
+
Donald Becker's driver development site:
+ http://www.scyld.com
http://cesdis.gsfc.nasa.gov/linux/
Don's vortex-diag program is useful for inspecting the NIC's state:
+ http://www.scyld.com/diag/#pci-diags
http://cesdis.gsfc.nasa.gov/linux/diag/vortex-diag.c
Don's mii-diag program may be used for inspecting and manipulating the
NIC's Media Independent Interface subsystem:
+ http://www.scyld.com/diag/#mii-diag
http://cesdis.gsfc.nasa.gov/linux/diag/#mii-diag
3Com's documentation for many NICs, including the ones supported by
http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3
+Autonegotiation notes
+---------------------
+
+ The driver uses a one-minute heartbeat for adapting to changes in
+ the external LAN environment. This means that when, for example, a
+ machine is unplugged from a hubbed 10baseT LAN plugged into a
+ switched 100baseT LAN, the throughput will be quite dreadful for up
+ to sixty seconds. Be patient.
-Cisco interoperability note from Walter Wong <wcw+@CMU.EDU>:
+ Cisco interoperability note from Walter Wong <wcw+@CMU.EDU>:
On a side note, adding HAS_NWAY seems to share a problem with the
Cisco 6509 switch. Specifically, you need to change the spanning
we've noticed for a while but haven't had the time to track down.
+Reporting and diagnosing problems
+---------------------------------
+
+If the driver plays up, there are a number of things you can do analyse
+the problem and to help others do this:
+
+- Turn on debugging in the driver
+ Add 'debug=7' to /etc/modules.conf (/etc/conf.modules)
+ Change 'vortex_debug' to 7 in the source code.
+
+- Send all kernel logs, starting with the first probe of the card.
+
+- Run 'mii-diag -v' to show the state of the Media Independent
+ Interface. If the card sometimes works and sometimes doesn't, run
+ 'mii-diag -v' in both states.
+
+- Please run 'vortex-diag -aaee' in both good and bad states. This
+ show the NIC's registers and EEPROM contents.
+
+- Describe your setup: 10baseT, 100baseT, full/half duplex, etc.
+
+- Note any additional module insertion commands you're using.
+
+- Try different media type settings (see above).
+
+- Try inserting the module with 'extra_reset=1' (or compile this into
+ the driver).
+
+
Copyright (C) 1999, 2000 David E. Nelson
-Mar. 23, 2000
+April 26, 2000
CHANGES
-- Amended for Linux-2.3.40
+- Amended for Linux-2.3.99-pre6-3
- Updated for multiple scanner support
-
INTRODUCTION
This document will hopefully provide enough info on how to get SANE
interface. The majority of HP Scanners support the Scanner Control
Language (SCL) which is both published by HP and supported by SANE.
The only HP Scanners that I'm aware of that do not support SCL are the
-4200C and the 3300C. All other HP scanners with USB interfaces should
-work (4100C, 5200C, 6200C, and 6300C). Of course as HP releases new
-scanners this information may change.
+4200C ,3300C, and the PhotoSmart S20. All other HP scanners with USB
+interfaces should work (4100C, 5200C, 6200C, and 6300C) as do models
+that are derived from the models above. ie the 6350C which is a 6300C
+with a transparency adaptor included with the scanner at time of
+purchase. Of course as HP releases new scanners this information may
+change.
REQUIREMENTS
OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW?
-NOTE: $INSTALL_DIR is the location where SANE is installed. It may
-be /usr/local, /usr, /opt or somewhere else. If you don't know, ask
-your system administrator.
+NOTE: $INSTALL_DIR is the location where SANE is installed. It may be
+/usr/local, /usr, /opt or somewhere else. If you don't know, ask your
+system administrator.
1) Make sure that you have the libsane-hp.* libraries under the
$INSTALL_DIR/lib/sane/ directory. If you don't, then the HP backend
option connect-device
NOTE: If you are using multiple scanners, make sure to have the correct
-devince, ie /dev/usbscanner0. See scanner.txt for more info.
+device, ie /dev/usbscanner0. See scanner.txt for more info.
3) You should now be able to use SANE (xscanimage or scanimage).
Don't forget to read any relevant man pages regarding the usage of
-SANE. If you have other entries uncommented in dll.conf, you may have
-to specify the device to (x)scanimage. Again, `man` is your friend.
-The xscanimage (1) man page has info on how to get 'The Gimp' to work
-with xscanimage. Note that Gimp support must be compiled into SANE
-for it work. If you are dealing with a RedHat system, this means that
-you'll also need to install the gimp-devel rpm package.
+SANE. If you have other entries uncommented in 'dll.conf', you may
+have to specify the device to (x)scanimage. Again, `man` is your
+friend. The xscanimage (1) man page has info on how to get 'The Gimp'
+to work with xscanimage. Note that Gimp support must be compiled into
+SANE for it to work. If you are dealing with a RedHat system, this
+means that you'll also need to install the gimp-devel rpm package
+prior to compiling SANE.
NOTE: The issues regarding core dumping by (x)scanimage have (or seem
to be thus far) been resolved with version 0.2+ of the USB scanner
Copyright (C) 1999, 2000 David E. Nelson
-Mar. 23, 2000
+April 26, 2000
CHANGES
-- Amended for linux-2.3.40
+- Amended for linux-2.3.99-pre6-3
- Appended hp_scan.c to end of this README
- Removed most references to HP
- Updated uhci/ohci host controller info
- Updated support for multiple scanner support
- Updated supported scanners list
-
+- Updated usbdevfs info
+- Spellcheck
OVERVIEW
-This README will address issues regarding how to configure the kernel
+This README addresses issues regarding how to configure the kernel
to access a USB scanner. Although the driver was originally conceived
for USB HP scanners, it's general enough so that it can be used with
other scanners. Also, one can now pass the USB Vendor and Product
ID's using module parameters for unknown scanners. Refer to the
-document scanner_hp_sane.txt for guidance on how to configure SANE to
+document scanner-hp-sane.txt for guidance on how to configure SANE to
use a USB HP Scanner.
A Linux kernel with USB Scanner support enabled.
'lspci' which is only needed to determine the type of USB hardware
-available in your machine.
+available/installed in your machine.
CONFIGURATION
-Using `lspci -v`, determine the type of USB hardware available.
+Using `lspci -v`, determine the type of USB hardware available/installed.
If you see something like:
hardware (determined from the steps above), 'USB Scanner support', and
'Preliminary USB device filesystem'. Compile and install the modules
(you may need to execute `depmod -a` to update the module
-dependencies). Testing was performed only as modules, YMMV.
+dependencies). If any of the USB sections were compiled into the
+kernel, a reboot is necessary. NOTE: Updating the boot disk with
+'lilo' may also be required. Testing was performed only as modules,
+YMMV.
Beginning with version 0.4 of the driver, up to 16 scanners can be
connected/used simultaneously. If you intend to use more than
`mknod /dev/usb/scanner15 180 63`
-If you forsee using only one scanner:
+If you foresee using only one scanner it is best to:
`mknod /dev/usbscanner0 c 180 48`
`ln -s /dev/usbscanner0 /dev/usbscanner`
Set appropriate permissions for /dev/usbscanner[0-15] (don't forget
about group and world permissions). Both read and write permissions
-are required for proper operation.
+are required for proper operation. For example:
+ `chmod 666 /dev/usbscanner0`
Load the appropriate modules (if compiled as modules):
SCL (Scanner Control Language). Known HP scanner that support SCL are
the 4100, 5200, 6200, the 6300 -- note that the 4200 is *not*
supported since it does not understand SCL; it's also strongly
-suspected that the 3300 is not SCL compliant. Hp_scan.c's purpose is
-to test the driver without having to retrieve/configure SANE.
-Hp_scan.c will scan the entire bed and put the output into a file
-called 'out.dat' in the current directory. The data in the file is
-raw data so it's not very useful for imaging.
-
+suspected that the 3300 and the PhotoSmart S20 are not SCL compliant.
+Hp_scan.c's purpose is to test the driver without having to
+retrieve/configure SANE. Hp_scan.c will scan the entire bed and put
+the output into a file called 'out.dat' in the current directory. The
+data in the file is raw data so it's not very useful for imaging.
+
+MESSAGES
+
+On occassion the message 'usb_control/bulk_msg: timeout' or something
+similar will appear in '/var/adm/messages' or on the console or both,
+depending on how your system is configured. This is a side effect
+that scanners are sometimes very slow at warming up and/or
+initialiazing. In most cases, however, only several of these messages
+should appear and is generally considered to be normal. If you see
+a message of the type 'excessive NAK's received' then this should
+be considered abnormal and generally indicates that the USB system is
+unable to communicate with the scanner for some particular reason.
SUPPORTED SCANNERS
At the time of this writing, the following scanners were supported by
scanner.c:
- Acer
-
- Prisa AcerScan 620U
-
- Agfa
-
- SnapScan 1212U, SnapScan Touch
-
- Genius
-
- ColorPage Vivid Pro
-
- Hewlett Packard
-
- 3300, 4100, 4200, 5200, 6200, 6300, PhotoSmart S20
-
- Microtek
-
- ScanMaker X6-X6U, Phantom 336CX - C3, Phantom C6, ScanMaker V6USL,
- ScanMaker V6UL - SpicyU
-
- Mustek
+ Acer
+ Prisa Acerscan 620U & 640U (!)
+ Prisa AcerScan 620U (!)
+ Agfa
+ SnapScan 1212U
+ Another SnapScan 1212U (?)
+ SnapScan Touch
+ Colorado -- See Primax/Colorado below
+ Epson -- See Seiko/Epson below
+ Genius
+ ColorPage-Vivid Pro
+ Hewlett Packard
+ 3300C
+ 4100C
+ 4200C
+ PhotoSmart S20
+ 5200C
+ 6200C
+ 6300C
+ Microtek
+ ScanMaker X6 - X6U
+ Phantom 336CX - C3
+ Phantom 336CX - C3 #2
+ Phantom C6
+ ScanMaker V6USL
+ ScanMaker V6USL #2
+ ScanMaker V6UL - SpicyU
+ Mustek
+ 1200 CU
+ Primax/Colorado
+ G2-300 #1
+ G2-600 #1
+ G2E-300 #1
+ ReadyScan 636i
+ G2-300 #2
+ G2-600 #2
+ G2E-300 #2
+ G2E-600
+ Colorado USB 9600
+ Colorado USB 19200
+ Colorado 600u
+ Colorado 1200u
+ Seiko/Epson Corp.
+ Perfection 636U and 636Photo
+ Perfection 610
+ Perfection 1200U and 1200Photo
+ Umax
+ Astra 1220U
+ Astra 1236U
+ Astra 2000U
+ Astra 2200U
+ Visioneer
+ OneTouch 5300
+ OneTouch 7600 duplicate ID (!)
+ 6100
- 1200 CU
- Primax/Colorado
-
- G2-300, G2-600, G2E-300, G2E-600, ReadyScan 636i, Colorado USB
- 19200, Colorado 600u, Colorado 1200u
-
- Seiko/Epson
-
- Perfection Perfection 610, Perfection 636U/636Photo, Perfection
- 1200U/1200Photo
-
- Umax
+MODULE PARAMETERS
- Astra 1220U, 1236U, 2000U
+If you have a device that you wish to experiment with or try using
+this driver with, but the Vendor and Product ID's are not coded in,
+don't despair. If the driver was compiled as a module, you can pass
+options to the driver. Simply add
- Visioneer
+ options scanner vendor=0x#### product=0x****
- OneTouch 5300, OneTouch 7600, 6100,
+to the /etc/modules.conf file replacing the #'s and the *'s with the
+correct ID's. The ID's can be retrieved from the messages file or
+using `cat /proc/bus/usb/devices`. Note that USB /proc support must be
+enabled during kernel configuration. If the 'scanner' module is
+already loaded into memory, it must be reloaded for the module
+parameters to take effect. In essence, `rmmod scanner; modprobe
+scanner` must be performed.
+**NOTE**: In later kernels (2.3.38+), a new filesystem was introduced,
+usbdevfs. To mount the filesystem, issue the command (as root):
- User Specified. See MODULE PARAMETERS for details.
+ mount -t usbdevfs /proc/bus/usb /proc/bus/usb
+An alternative and more permanent method would be to add
-MODULE PARAMETERS
+ none /proc/bus/usb usbdevfs defaults 0 0
-If you have a device that you wish to experiment with or try using
-this driver with, but the Vendor and Product ID's are not coded in,
-don't despair. If the driver was compiled as a module, you can pass
-options to the driver. Simply add 'options scanner vendor=0x####
-product=0x****' to the conf.modules/modules.conf file replacing the
-#'s and the *'s with the correct ID's. The ID's can be retrieved from
-the messages file or using `cat /proc/bus/usb/devices` if USB /proc
-support was selected during kernel configuration. **NOTE**:In later
-kernels (2.3.38+), a new filesystem was introduced, usbdevfs. To
-mount the filesystem, issue the command `mount -t usbdevfs
-/proc/bus/usb /proc/bus/usb`. You can then issue ` cat
-/proc/bus/usb/devices` to extract USB device information.
+to /etc/fstab. This will mount usbdevfs at each reboot. You can then
+issue `cat /proc/bus/usb/devices` to extract USB device information.
BUGS
-If you encounter any problems feel free to drop me an email.
+Just look at the list of fixes in the source files. So, if you
+encounter any problems feel free to drop me an email.
David /\/elson
dnelson@jump.net
RAGE128 FRAMEBUFFER DISPLAY DRIVER
P: Brad Douglas
M: brad@neruo.com
-L: linux-fbdev@vuser.vc.union.edu
+L: linux-fbdev@vuser.vu.union.edu
S: Maintained
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
+unsigned int pcibios_max_latency = 255;
+
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat < 16) {
- printk("PCI: Increasing latency timer of device %s to 64\n", dev->slot_name);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
- }
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
/* pci-i386.c */
+extern unsigned int pcibios_max_latency;
+
void pcibios_resource_survey(void);
int pcibios_enable_resources(struct pci_dev *);
extern unsigned int pcibios_irq_mask;
+void pcibios_irq_init(void);
void pcibios_fixup_irqs(void);
int pcibios_lookup_irq(struct pci_dev *dev, int assign);
}
}
+static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+ pirq--;
+ if (pirq < 8) {
+ u8 x;
+ unsigned reg = 0x48 + (pirq >> 1);
+ pci_read_config_byte(router, reg, &x);
+ return irqmap[(pirq & 1) ? (x >> 4) : (x & 0x0f)];
+ }
+ return 0;
+}
+
static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
- static unsigned char irqmap[16] = {
- 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15
- };
+ static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
unsigned int val = irqmap[irq];
pirq--;
if (val && pirq < 8) {
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
- { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL, pirq_ali_set },
+ { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set },
}
#endif
if (!(pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) {
- DBG("PCI: Interrupt router not found\n");
+ DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+ /* fall back to default router */
+ pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1;
return;
}
if (rt->rtr_vendor) {
return 1;
}
-void __init pcibios_fixup_irqs(void)
+void __init pcibios_irq_init(void)
{
- struct pci_dev *dev;
- u8 pin;
-
- DBG("PCI: IRQ fixup\n");
+ DBG("PCI: IRQ init\n");
pirq_table = pirq_find_routing_table();
#ifdef CONFIG_PCI_BIOS
if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
pirq_peer_trick();
pirq_find_router();
}
+}
+
+void __init pcibios_fixup_irqs(void)
+{
+ struct pci_dev *dev;
+ u8 pin;
+ DBG("PCI: IRQ fixup\n");
pci_for_each_dev(dev) {
/*
* If the BIOS has set an out of range IRQ number, just ignore it.
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/segment.h>
#include <asm/io.h>
outl (tmp, 0xCF8);
__restore_flags(flags);
printk("PCI: Using configuration type 1\n");
+ request_region(0xCF8, 8, "PCI conf1");
return &pci_direct_conf1;
}
outl (tmp, 0xCF8);
pci_sanity_check(&pci_direct_conf2)) {
__restore_flags(flags);
printk("PCI: Using configuration type 2\n");
+ request_region(0xCF8, 4, "PCI conf2");
return &pci_direct_conf2;
}
}
d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
}
+static void __init pci_fixup_latency(struct pci_dev *d)
+{
+ /*
+ * SiS 5597 and 5598 chipsets require latency timer set to
+ * at most 32 to avoid lockups.
+ */
+ DBG("PCI: Setting max latency to 32\n");
+ pcibios_max_latency = 32;
+}
+
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency },
{ 0 }
};
printk("PCI: Probing PCI hardware\n");
pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
- pcibios_fixup_irqs();
+ pcibios_irq_init();
pcibios_fixup_peer_bridges();
+ pcibios_fixup_irqs();
pcibios_resource_survey();
#ifdef CONFIG_PCI_BIOS
* Added proper L2 cache detection for Coppermine
* Dragan Stancevic <visitor@valinux.com>, October 1999
*
- * Added the origninal array for capability flags but forgot to credit
+ * Added the original array for capability flags but forgot to credit
* myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff
* Jauder Ho <jauderho@carumba.com>, January 2000
+ *
+ * Detection for Celeron coppermine, identify_cpu() overhauled,
+ * and a few other clean ups.
+ * Dave Jones <dave@powertweak.com>, April 2000
*
*/
static int __init get_model_name(struct cpuinfo_x86 *c)
{
- unsigned int n, dummy, *v, ecx, edx;
+ unsigned int n, dummy, *v;
/* Actually we must have cpuid or we could never have
* figured out that this was AMD/Cyrix from the vendor info :-).
cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
c->x86_model_id[48] = 0;
- /* Set MTRR capability flag if appropriate */
-
- if(c->x86_vendor==X86_VENDOR_AMD)
- {
- if(boot_cpu_data.x86 == 5) {
- if((boot_cpu_data.x86_model == 9) ||
- ((boot_cpu_data.x86_model == 8) &&
- (boot_cpu_data.x86_mask >= 8)))
- c->x86_capability |= X86_FEATURE_MTRR;
- }
-
- if (n >= 0x80000005){
- cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
- printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
- ecx>>24, edx>>24);
- c->x86_cache_size=(ecx>>24)+(edx>>24);
- }
- if (n >= 0x80000006){
- cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
- printk("CPU: L2 Cache: %dK\n", ecx>>16);
- c->x86_cache_size=(ecx>>16);
- }
- }
return 1;
}
{
u32 l, h;
unsigned long flags;
+ unsigned int n, dummy, ecx, edx;
int mbytes = max_mapnr >> (20-PAGE_SHIFT);
-
+
int r=get_model_name(c);
-
+
/*
- * Now do the cache operations.
+ * Set MTRR capability flag if appropriate
+ */
+ if(boot_cpu_data.x86 == 5) {
+ if((boot_cpu_data.x86_model == 9) ||
+ ((boot_cpu_data.x86_model == 8) &&
+ (boot_cpu_data.x86_mask >= 8)))
+ c->x86_capability |= X86_FEATURE_MTRR;
+ }
+
+ /*
+ * Now do the cache operations.
*/
-
switch(c->x86)
{
case 5:
case 6: /* An Athlon. We can trust the BIOS probably */
break;
}
+
+ cpuid(0x80000000, &n, &dummy, &dummy, &dummy);
+ if (n >= 0x80000005) {
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk("CPU: L1 I Cache: %dK L1 D Cache: %dK\n",
+ ecx>>24, edx>>24);
+ c->x86_cache_size=(ecx>>24)+(edx>>24);
+ }
+ if (n >= 0x80000006) {
+ cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
+ printk("CPU: L2 Cache: %dK\n", ecx>>16);
+ c->x86_cache_size=(ecx>>16);
+ }
+
return r;
}
/* It isnt really a PCI quirk directly, but the cure is the
same. The MediaGX has deep magic SMM stuff that handles the
SB emulation. It thows away the fifo on disable_dma() which
- is wrong and ruins the audio.
+ is wrong and ruins the audio.
- Bug2: VSA1 has a wrap bug so that using maximum sized DMA
- causes bad things. According to NatSemi VSA2 has another
- bug to do with 'hlt'. I've not seen any boards using VSA2
- and X doesn't seem to support it either so who cares 8).
- VSA1 we work around however.
+ Bug2: VSA1 has a wrap bug so that using maximum sized DMA
+ causes bad things. According to NatSemi VSA2 has another
+ bug to do with 'hlt'. I've not seen any boards using VSA2
+ and X doesn't seem to support it either so who cares 8).
+ VSA1 we work around however.
*/
isa_dma_bridge_buggy = 2;
#endif
c->x86_cache_size=16; /* Yep 16K integrated cache thats it */
-
+
/* GXm supports extended cpuid levels 'ala' AMD */
if (c->cpuid_level == 2) {
get_model_name(c); /* get CPU marketing name */
void __init identify_cpu(struct cpuinfo_x86 *c)
{
- int i;
+ int i=0;
char *p = NULL;
c->loops_per_sec = loops_per_sec;
get_cpu_vendor(c);
- if (c->x86_vendor == X86_VENDOR_UNKNOWN &&
- c->cpuid_level < 0)
- return;
+ switch (c->x86_vendor) {
- if (c->x86_vendor == X86_VENDOR_CYRIX) {
- cyrix_model(c);
- return;
- }
+ case X86_VENDOR_UNKNOWN:
+ if (c->cpuid_level < 0)
+ return;
+ break;
- if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
- return;
+ case X86_VENDOR_CYRIX:
+ cyrix_model(c);
+ return;
- if (c->x86_vendor == X86_VENDOR_CENTAUR) {
- centaur_model(c);
- return;
- }
-
- if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL)
- {
- if(c->x86_capability&(1<<18))
- {
- /* Disable processor serial number on Intel Pentium III
- from code by Phil Karn */
- unsigned long lo,hi;
- rdmsr(0x119,lo,hi);
- lo |= 0x200000;
- wrmsr(0x119,lo,hi);
- printk(KERN_INFO "Pentium-III serial number disabled.\n");
- }
- }
+ case X86_VENDOR_AMD:
+ if (amd_model(c))
+ return;
+ break;
- if (c->cpuid_level > 1) {
- /* supports eax=2 call */
- int edx, dummy;
+ case X86_VENDOR_CENTAUR:
+ centaur_model(c);
+ return;
- cpuid(2, &dummy, &dummy, &dummy, &edx);
+ case X86_VENDOR_INTEL:
+ if(c->x86_capability&(1<<18)) {
+ /* Disable processor serial number on Intel Pentium III
+ from code by Phil Karn */
+ unsigned long lo,hi;
+ rdmsr(0x119,lo,hi);
+ lo |= 0x200000;
+ wrmsr(0x119,lo,hi);
+ printk(KERN_INFO "Pentium-III serial number disabled.\n");
+ }
- /* We need only the LSB */
- edx &= 0xff;
+ if (c->cpuid_level > 1) {
+ /* supports eax=2 call */
+ int edx, dummy;
- switch (edx) {
- case 0x40:
- c->x86_cache_size = 0;
- break;
+ cpuid(2, &dummy, &dummy, &dummy, &edx);
- case 0x41:
- c->x86_cache_size = 128;
- break;
+ /* We need only the LSB */
+ edx &= 0xff;
- case 0x42:
- case 0x82: /*Detect 256-Kbyte cache on Coppermine*/
- c->x86_cache_size = 256;
- break;
+ switch (edx) {
+ case 0x40:
+ c->x86_cache_size = 0;
+ break;
- case 0x43:
- c->x86_cache_size = 512;
- break;
+ case 0x41:
+ c->x86_cache_size = 128;
+ break;
- case 0x44:
- c->x86_cache_size = 1024;
- break;
+ case 0x42:
+ case 0x82: /*Detect 256-Kbyte cache on Coppermine*/
+ c->x86_cache_size = 256;
+ break;
- case 0x45:
- c->x86_cache_size = 2048;
- break;
+ case 0x43:
+ c->x86_cache_size = 512;
+ break;
- default:
- c->x86_cache_size = 0;
- break;
- }
- }
+ case 0x44:
+ c->x86_cache_size = 1024;
+ break;
+
+ case 0x45:
+ c->x86_cache_size = 2048;
+ break;
+ default:
+ c->x86_cache_size = 0;
+ break;
+ }
+ }
+
+ /* Names for the Pentium II/Celeron processors
+ detectable only by also checking the cache size.
+ Dixon is NOT a Celeron. */
+ if (cpu_models[i].x86 == 6) {
+ switch (c->x86_model) {
+ case 5:
+ if (c->x86_cache_size == 0)
+ p = "Celeron (Covington)";
+ if (c->x86_cache_size == 256)
+ p = "Mobile Pentium II (Dixon)";
+ break;
+
+ case 6:
+ if (c->x86_cache_size == 128)
+ p = "Celeron (Mendocino)";
+ break;
+
+ case 8:
+ if (c->x86_cache_size == 128)
+ p = "Celeron (Coppermine)";
+ break;
+ }
+ }
+ if (p!=NULL)
+ goto name_decoded;
+
+ break;
+ }
+
+
for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) {
if (cpu_models[i].vendor == c->x86_vendor &&
cpu_models[i].x86 == c->x86) {
if (c->x86_model <= 16)
p = cpu_models[i].model_names[c->x86_model];
-
- /* Names for the Pentium II/Celeron processors
- detectable only by also checking the cache size.
- Dixon is NOT a Celeron. */
- if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
- && (cpu_models[i].x86 == 6))
- {
- if(c->x86_model == 5 && c->x86_cache_size == 0)
- p = "Celeron (Covington)";
- else if(c->x86_model == 6 && c->x86_cache_size == 128)
- p = "Celeron (Mendocino)";
- else if(c->x86_model == 5 && c->x86_cache_size == 256)
- p = "Mobile Pentium II (Dixon)";
- }
}
}
+name_decoded:
+
if (p) {
strcpy(c->x86_model_id, p);
return;
void __init dodgy_tsc(void)
{
get_cpu_vendor(&boot_cpu_data);
-
+
if(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)
- {
return;
- }
+
cyrix_model(&boot_cpu_data);
}
continue;
#endif
p += sprintf(p,"processor\t: %d\n"
- "vendor_id\t: %s\n"
- "cpu family\t: %c\n"
- "model\t\t: %d\n"
- "model name\t: %s\n",
- n,
- c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
- c->x86 + '0',
- c->x86_model,
- c->x86_model_id[0] ? c->x86_model_id : "unknown");
+ "vendor_id\t: %s\n"
+ "cpu family\t: %c\n"
+ "model\t\t: %d\n"
+ "model name\t: %s\n",
+ n,
+ c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ c->x86 + '0',
+ c->x86_model,
+ c->x86_model_id[0] ? c->x86_model_id : "unknown");
if (c->x86_mask || c->cpuid_level >= 0)
p += sprintf(p, "stepping\t: %d\n", c->x86_mask);
switch (c->x86_vendor) {
case X86_VENDOR_CYRIX:
- x86_cap_flags[24] = "cxmmx";
- break;
+ x86_cap_flags[24] = "cxmmx";
+ break;
case X86_VENDOR_AMD:
- if (c->x86 == 5 && c->x86_model == 6)
- x86_cap_flags[10] = "sep";
- if (c->x86 < 6)
- x86_cap_flags[16] = "fcmov";
- x86_cap_flags[22] = "mmxext";
- x86_cap_flags[30] = "3dnowext";
- x86_cap_flags[31] = "3dnow";
- break;
+ if (c->x86 == 5 && c->x86_model == 6)
+ x86_cap_flags[10] = "sep";
+ if (c->x86 < 6)
+ x86_cap_flags[16] = "fcmov";
+ x86_cap_flags[22] = "mmxext";
+ x86_cap_flags[30] = "3dnowext";
+ x86_cap_flags[31] = "3dnow";
+ break;
case X86_VENDOR_INTEL:
- x86_cap_flags[16] = "pat";
- x86_cap_flags[24] = "fxsr";
- break;
+ x86_cap_flags[16] = "pat";
+ x86_cap_flags[24] = "fxsr";
+ break;
case X86_VENDOR_CENTAUR:
- if (c->x86_model >=8) /* Only Winchip2 and above */
- x86_cap_flags[31] = "3dnow";
- break;
+ if (c->x86_model >=8) /* Only Winchip2 and above */
+ x86_cap_flags[31] = "3dnow";
+ break;
default:
- /* Unknown CPU manufacturer. Transmeta ? :-) */
- break;
+ /* Unknown CPU manufacturer. Transmeta ? :-) */
+ break;
}
sep_bug = c->x86_vendor == X86_VENDOR_INTEL &&
for ( i = 0 ; i < 32 ; i++ )
if ( c->x86_capability & (1 << i) )
p += sprintf(p, " %s", x86_cap_flags[i]);
+
p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n",
- (c->loops_per_sec+2500)/500000,
- ((c->loops_per_sec+2500)/5000) % 100);
+ (c->loops_per_sec+2500)/500000,
+ ((c->loops_per_sec+2500)/5000) % 100);
}
return p - buffer;
}
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- {
- int fault = handle_mm_fault(mm, vma, address, write);
- if (fault < 0)
- goto out_of_memory;
- if (!fault)
- goto do_sigbus;
+ switch (handle_mm_fault(mm, vma, address, write)) {
+ case 1:
+ tsk->min_flt++;
+ break;
+ case 2:
+ tsk->maj_flt++;
+ break;
+ case 0:
+ goto do_sigbus;
+ default:
+ goto out_of_memory;
}
/*
--- /dev/null
+#
+# MPC8260 Communication options
+#
+if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'MPC8260 Communication Options'
+ bool 'CPM SCC Ethernet' CONFIG_SCC_ENET
+ if [ "$CONFIG_SCC_ENET" = "y" ]; then
+ bool 'Ethernet on SCC1' CONFIG_SCC1_ENET
+ if [ "$CONFIG_SCC1_ENET" != "y" ]; then
+ bool 'Ethernet on SCC2' CONFIG_SCC2_ENET
+ fi
+ fi
+ bool 'FCC Ethernet' CONFIG_FCC_ENET
+ if [ "$CONFIG_FCC_ENET" = "y" ]; then
+ bool 'Ethernet on FCC1' CONFIG_FCC1_ENET
+ if [ "$CONFIG_FCC1_ENET" != "y" ]; then
+ bool 'Ethernet on FCC2' CONFIG_FCC2_ENET
+ fi
+ fi
+ endmenu
+fi
--- /dev/null
+#
+# Makefile for the linux MPC8xx ppc-specific parts of comm processor
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := 8260_io.a
+O_OBJS = commproc.o uart.o
+
+ifdef CONFIG_FCC_ENET
+O_OBJS += fcc.o
+endif
+ifdef CONFIG_SCC_ENET
+O_OBJS += enet.o
+endif
+
+include $(TOPDIR)/Rules.make
--- /dev/null
+
+/*
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <asm/irq.h>
+#include <asm/mpc8260.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/immap_8260.h>
+#include <asm/cpm_8260.h>
+
+static uint dp_alloc_base; /* Starting offset in DP ram */
+static uint dp_alloc_top; /* Max offset + 1 */
+static uint host_buffer; /* One page of host buffer */
+static uint host_end; /* end + 1 */
+cpm8260_t *cpmp; /* Pointer to comm processor space */
+
+/* We allocate this here because it is used almost exclusively for
+ * the communication processor devices.
+ */
+immap_t *immr;
+
+void
+m8260_cpm_reset(void)
+{
+ volatile immap_t *imp;
+ volatile cpm8260_t *commproc;
+ uint vpgaddr;
+
+ immr = imp = (volatile immap_t *)IMAP_ADDR;
+ commproc = &imp->im_cpm;
+
+ /* Reclaim the DP memory for our use.
+ */
+ dp_alloc_base = CPM_DATAONLY_BASE;
+ dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+
+ /* Set the host page for allocation.
+ */
+ host_buffer =
+ (uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
+ host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
+
+ vpgaddr = host_buffer;
+
+ /* Tell everyone where the comm processor resides.
+ */
+ cpmp = (cpm8260_t *)commproc;
+}
+
+/* Allocate some memory from the dual ported ram. We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint
+m8260_cpm_dpalloc(uint size)
+{
+ uint retloc;
+
+ if ((dp_alloc_base + size) >= dp_alloc_top)
+ return(CPM_DP_NOSPACE);
+
+ retloc = dp_alloc_base;
+ dp_alloc_base += size;
+
+ return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8260_cpm_hostalloc(uint size)
+{
+ uint retloc;
+
+ if ((host_buffer + size) >= host_end)
+ return(0);
+
+ retloc = host_buffer;
+ host_buffer += size;
+
+ return(retloc);
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK (((bd_t *)__res)->bi_brgfreq * 1000000)
+#define BRG_UART_CLK (BRG_INT_CLK/16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8260_cpm_setbrg(uint brg, uint rate)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8260_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
--- /dev/null
+/*
+ * Ethernet driver for Motorola MPC8260.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software Inc. (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * I copied this from the 8xx CPM Ethernet driver, so follow the
+ * credits back through that.
+ *
+ * This version of the driver is somewhat selectable for the different
+ * processor/board combinations. It works for the boards I know about
+ * now, and should be easily modified to include others. Some of the
+ * configuration information is contained in "commproc.h" and the
+ * remainder is here.
+ *
+ * Buffer descriptors are kept in the CPM dual port RAM, and the frame
+ * buffers are in the host memory.
+ *
+ * Right now, I am very watseful with the buffers. I allocate memory
+ * pages and then divide them into 2K frame buffers. This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <asm/immap_8260.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8260.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/cpm_8260.h>
+#include <asm/irq.h>
+
+/*
+ * Theory of Operation
+ *
+ * The MPC8260 CPM performs the Ethernet processing on an SCC. It can use
+ * an aribtrary number of buffers on byte boundaries, but must have at
+ * least two receive buffers to prevent constant overrun conditions.
+ *
+ * The buffer descriptors are allocated from the CPM dual port memory
+ * with the data buffers allocated from host memory, just like all other
+ * serial communication protocols. The host memory buffers are allocated
+ * from the free page pool, and then divided into smaller receive and
+ * transmit buffers. The size of the buffers should be a power of two,
+ * since that nicely divides the page. This creates a ring buffer
+ * structure similar to the LANCE and other controllers.
+ *
+ * Like the LANCE driver:
+ * The driver runs as two independent, single-threaded flows of control. One
+ * is the send-packet routine, which enforces single-threaded use by the
+ * cep->tx_busy flag. The other thread is the interrupt handler, which is
+ * single threaded by the hardware and other software.
+ */
+
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
+/* The number of Tx and Rx buffers. These are allocated from the page
+ * pool. The code may assume these are power of two, so it is best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter. We just use
+ * the skbuffer directly.
+ */
+#define CPM_ENET_RX_PAGES 4
+#define CPM_ENET_RX_FRSIZE 2048
+#define CPM_ENET_RX_FRPPG (PAGE_SIZE / CPM_ENET_RX_FRSIZE)
+#define RX_RING_SIZE (CPM_ENET_RX_FRPPG * CPM_ENET_RX_PAGES)
+#define TX_RING_SIZE 8 /* Must be power of two */
+#define TX_RING_MOD_MASK 7 /* for this to work */
+
+/* The CPM stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+/* The CPM buffer descriptors track the ring buffers. The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors. The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller. The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions. The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct scc_enet_private {
+ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+ struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ ushort skb_cur;
+ ushort skb_dirty;
+
+ /* CPM dual port RAM relative addresses.
+ */
+ cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */
+ cbd_t *tx_bd_base;
+ cbd_t *cur_rx, *cur_tx; /* The next free ring entry */
+ cbd_t *dirty_tx; /* The ring entries to be free()ed. */
+ scc_t *sccp;
+ struct net_device_stats stats;
+ uint tx_full;
+ spinlock_t lock;
+};
+
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+
+/* These will be configurable for the SCC choice.
+*/
+#define CPM_ENET_BLOCK CPM_CR_SCC1_SBLOCK
+#define CPM_ENET_PAGE CPM_CR_SCC1_PAGE
+#define PROFF_ENET PROFF_SCC1
+#define SCC_ENET 0
+#define SIU_INT_ENET SIU_INT_SCC1
+
+/* These are both board and SCC dependent....
+*/
+#define PD_ENET_RXD ((uint)0x00000001)
+#define PD_ENET_TXD ((uint)0x00000002)
+#define PD_ENET_TENA ((uint)0x00000004)
+#define PC_ENET_RENA ((uint)0x00020000)
+#define PC_ENET_CLSN ((uint)0x00000004)
+#define PC_ENET_TXCLK ((uint)0x00000800)
+#define PC_ENET_RXCLK ((uint)0x00000400)
+#define CMX_CLK_ROUTE ((uint)0x25000000)
+#define CMX_CLK_MASK ((uint)0xff000000)
+
+/* Specific to a board.
+*/
+#define PC_EST8260_ENET_LOOPBACK ((uint)0x80000000)
+#define PC_EST8260_ENET_SQE ((uint)0x40000000)
+#define PC_EST8260_ENET_NOTFD ((uint)0x20000000)
+
+static int
+scc_enet_open(struct net_device *dev)
+{
+
+ /* I should reset the ring buffers here, but I don't yet know
+ * a simple way to do that.
+ */
+ netif_start_queue(dev);
+ return 0; /* Always succeed */
+}
+
+static int
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+ volatile cbd_t *bdp;
+
+
+ /* Fill in a Tx ring entry */
+ bdp = cep->cur_tx;
+
+#ifndef final_version
+ if (bdp->cbd_sc & BD_ENET_TX_READY) {
+ /* Ooops. All transmit buffers are full. Bail out.
+ * This should not happen, since cep->tx_busy should be set.
+ */
+ printk("%s: tx queue full!.\n", dev->name);
+ return 1;
+ }
+#endif
+
+ /* Clear all of the status flags.
+ */
+ bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+ /* If the frame is short, tell CPM to pad it.
+ */
+ if (skb->len <= ETH_ZLEN)
+ bdp->cbd_sc |= BD_ENET_TX_PAD;
+ else
+ bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+
+ /* Set buffer length and buffer pointer.
+ */
+ bdp->cbd_datlen = skb->len;
+ bdp->cbd_bufaddr = __pa(skb->data);
+
+ /* Save skb pointer.
+ */
+ cep->tx_skbuff[cep->skb_cur] = skb;
+
+ cep->stats.tx_bytes += skb->len;
+ cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+
+ /* Push the data cache so the CPM does not get stale memory
+ * data.
+ */
+ flush_dcache_range((unsigned long)(skb->data),
+ (unsigned long)(skb->data + skb->len));
+
+ spin_lock_irq(&cep->lock);
+
+ /* Send it on its way. Tell CPM its ready, interrupt when done,
+ * its the last BD of the frame, and to put the CRC on the end.
+ */
+ bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+ dev->trans_start = jiffies;
+
+ /* If this was the last BD in the ring, start at the beginning again.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ if (bdp->cbd_sc & BD_ENET_TX_READY)
+ netif_stop_queue(dev);
+
+ cep->cur_tx = (cbd_t *)bdp;
+
+ spin_unlock_irq(&cep->lock);
+
+ return 0;
+}
+
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+scc_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ volatile struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ ushort int_events;
+ int must_restart;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get the interrupt events that caused us to be here.
+ */
+ int_events = cep->sccp->scc_scce;
+ cep->sccp->scc_scce = int_events;
+ must_restart = 0;
+
+ /* Handle receive event in its own function.
+ */
+ if (int_events & SCCE_ENET_RXF)
+ scc_enet_rx(dev_id);
+
+ /* Check for a transmit error. The manual is a little unclear
+ * about this, so the debug code until I get it figured out. It
+ * appears that if TXE is set, then TXB is not set. However,
+ * if carrier sense is lost during frame transmission, the TXE
+ * bit is set, "and continues the buffer transmission normally."
+ * I don't know if "normally" implies TXB is set when the buffer
+ * descriptor is closed.....trial and error :-).
+ */
+
+ /* Transmit OK, or non-fatal error. Update the buffer descriptors.
+ */
+ if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
+ bdp = cep->dirty_tx;
+ while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+ if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
+ break;
+
+ if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */
+ cep->stats.tx_heartbeat_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */
+ cep->stats.tx_window_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */
+ cep->stats.tx_aborted_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */
+ cep->stats.tx_fifo_errors++;
+ if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+ cep->stats.tx_carrier_errors++;
+
+
+ /* No heartbeat or Lost carrier are not really bad errors.
+ * The others require a restart transmit command.
+ */
+ if (bdp->cbd_sc &
+ (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
+ must_restart = 1;
+ cep->stats.tx_errors++;
+ }
+
+ cep->stats.tx_packets++;
+
+ /* Deferred means some collisions occurred during transmit,
+ * but we eventually sent the packet OK.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_DEF)
+ cep->stats.collisions++;
+
+ /* Free the sk buffer associated with this last transmit.
+ */
+ dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
+ cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+
+ /* Update pointer to next buffer descriptor to be transmitted.
+ */
+ if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+ bdp = cep->tx_bd_base;
+ else
+ bdp++;
+
+ /* I don't know if we can be held off from processing these
+ * interrupts for more than one frame time. I really hope
+ * not. In such a case, we would now want to check the
+ * currently available BD (cur_tx) and determine if any
+ * buffers between the dirty_tx and cur_tx have also been
+ * sent. We would want to process anything in between that
+ * does not have BD_ENET_TX_READY set.
+ */
+
+ /* Since we have freed up a buffer, the ring is no longer
+ * full.
+ */
+ if (cep->tx_full) {
+ if (netif_queue_stopped(dev)) {
+ netif_wake_queue(dev);
+ }
+ }
+
+ cep->dirty_tx = (cbd_t *)bdp;
+ }
+
+ if (must_restart) {
+ volatile cpm8260_t *cp;
+
+ /* Some transmit errors cause the transmitter to shut
+ * down. We now issue a restart transmit. Since the
+ * errors close the BD and update the pointers, the restart
+ * _should_ pick up without having to reset any of our
+ * pointers either.
+ */
+ cp = cpmp;
+ cp->cp_cpcr =
+ mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+ spin_unlock(&cep->lock);
+ }
+
+ /* Check for receive busy, i.e. packets coming but no place to
+ * put them. This "can't happen" because the receive interrupt
+ * is tossing previous frames.
+ */
+ if (int_events & SCCE_ENET_BSY) {
+ cep->stats.rx_dropped++;
+ printk("SCC ENET: BSY can't happen.\n");
+ }
+
+ return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+scc_enet_rx(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ volatile cbd_t *bdp;
+ struct sk_buff *skb;
+ ushort pkt_len;
+
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* First, grab all of the stats for the incoming packet.
+ * These get messed up if we get called due to a busy condition.
+ */
+ bdp = cep->cur_rx;
+
+for (;;) {
+ if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+ break;
+
+#ifndef final_version
+ /* Since we have allocated space to hold a complete frame, both
+ * the first and last indicators should be set.
+ */
+ if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+ (BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+ printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+ /* Frame too long or too short.
+ */
+ if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+ cep->stats.rx_length_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */
+ cep->stats.rx_frame_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */
+ cep->stats.rx_crc_errors++;
+ if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */
+ cep->stats.rx_crc_errors++;
+
+ /* Report late collisions as a frame error.
+ * On this error, the BD is closed, but we don't know what we
+ * have in the buffer. So, just drop this frame on the floor.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_CL) {
+ cep->stats.rx_frame_errors++;
+ }
+ else {
+
+ /* Process the incoming frame.
+ */
+ cep->stats.rx_packets++;
+ pkt_len = bdp->cbd_datlen;
+ cep->stats.rx_bytes += pkt_len;
+
+ /* This does 16 byte alignment, much more than we need.
+ */
+ skb = dev_alloc_skb(pkt_len);
+
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ cep->stats.rx_dropped++;
+ }
+ else {
+ skb->dev = dev;
+ skb_put(skb,pkt_len); /* Make room */
+ eth_copy_and_sum(skb,
+ (unsigned char *)__va(bdp->cbd_bufaddr),
+ pkt_len, 0);
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ }
+ }
+
+ /* Clear the status flags for this buffer.
+ */
+ bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+ /* Mark the buffer empty.
+ */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+ /* Update BD pointer to next entry.
+ */
+ if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+ bdp = cep->rx_bd_base;
+ else
+ bdp++;
+
+ }
+ cep->cur_rx = (cbd_t *)bdp;
+
+ return 0;
+}
+
+static int
+scc_enet_close(struct net_device *dev)
+{
+ /* Don't know what to do yet.
+ */
+ netif_stop_queue(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ return &cep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering. Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not. I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct scc_enet_private *cep;
+ struct dev_mc_list *dmi;
+ u_char *mcptr, *tdptr;
+ volatile scc_enet_t *ep;
+ int i, j;
+ cep = (struct scc_enet_private *)dev->priv;
+
+ /* Get pointer to SCC area in parameter RAM.
+ */
+ ep = (scc_enet_t *)dev->base_addr;
+
+ if (dev->flags&IFF_PROMISC) {
+
+ /* Log any net taps. */
+ printk("%s: Promiscuous mode enabled.\n", dev->name);
+ cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
+ } else {
+
+ cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
+
+ if (dev->flags & IFF_ALLMULTI) {
+ /* Catch all multicast addresses, so set the
+ * filter to all 1's.
+ */
+ ep->sen_gaddr1 = 0xffff;
+ ep->sen_gaddr2 = 0xffff;
+ ep->sen_gaddr3 = 0xffff;
+ ep->sen_gaddr4 = 0xffff;
+ }
+ else {
+ /* Clear filter and add the addresses in the list.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+
+ dmi = dev->mc_list;
+
+ for (i=0; i<dev->mc_count; i++) {
+
+ /* Only support group multicast for now.
+ */
+ if (!(dmi->dmi_addr[0] & 1))
+ continue;
+
+ /* The address in dmi_addr is LSB first,
+ * and taddr is MSB first. We have to
+ * copy bytes MSB first from dmi_addr.
+ */
+ mcptr = (u_char *)dmi->dmi_addr + 5;
+ tdptr = (u_char *)&ep->sen_taddrh;
+ for (j=0; j<6; j++)
+ *tdptr++ = *mcptr--;
+
+ /* Ask CPM to run CRC and set bit in
+ * filter mask.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE,
+ CPM_ENET_BLOCK, 0,
+ CPM_CR_SET_GADDR) | CPM_CR_FLG;
+ /* this delay is necessary here -- Cort */
+ udelay(10);
+ while (cpmp->cp_cpcr & CPM_CR_FLG);
+ }
+ }
+ }
+}
+
+/* Initialize the CPM Ethernet on SCC.
+ */
+int __init scc_enet_init(void)
+{
+ struct net_device *dev;
+ struct scc_enet_private *cep;
+ int i, j;
+ unsigned char *eap;
+ unsigned long mem_addr;
+ bd_t *bd;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile scc_t *sccp;
+ volatile scc_enet_t *ep;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ cp = cpmp; /* Get pointer to Communication Processor */
+
+ immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
+ io = &immap->im_ioport;
+
+ bd = (bd_t *)__res;
+
+ /* Allocate some private information.
+ */
+ cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+ __clear_user(cep,sizeof(*cep));
+ 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]);
+
+ /* And another to the SCC register area.
+ */
+ sccp = (volatile scc_t *)(&immap->im_scc[SCC_ENET]);
+ cep->sccp = (scc_t *)sccp; /* Keep the pointer handy */
+
+ /* Disable receive and transmit in case someone left it running.
+ */
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* Configure port C and D pins for SCC Ethernet. This
+ * won't work for all SCC possibilities....it will be
+ * board/port specific.
+ */
+ io->iop_pparc |=
+ (PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_pdirc &=
+ ~(PC_ENET_RENA | PC_ENET_CLSN | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc &=
+ ~(PC_ENET_RENA | PC_ENET_TXCLK | PC_ENET_RXCLK);
+ io->iop_psorc |= PC_ENET_CLSN;
+
+ io->iop_ppard |= (PD_ENET_RXD | PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird |= (PD_ENET_TXD | PD_ENET_TENA);
+ io->iop_pdird &= ~PD_ENET_RXD;
+ io->iop_psord |= PD_ENET_TXD;
+ io->iop_psord &= ~(PD_ENET_RXD | PD_ENET_TENA);
+
+ /* Configure Serial Interface clock routing.
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+ immap->im_cpmux.cmx_scr &= ~CMX_CLK_MASK;
+ immap->im_cpmux.cmx_scr |= CMX_CLK_ROUTE;
+
+ /* Allocate space for the buffer descriptors in the DP ram.
+ * These are relative offsets in the DP ram address space.
+ * Initialize base addresses for the buffer descriptors.
+ */
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
+ ep->sen_genscc.scc_rbase = i;
+ cep->rx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+ i = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
+ ep->sen_genscc.scc_tbase = i;
+ cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i];
+
+ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+ cep->cur_rx = cep->rx_bd_base;
+
+ ep->sen_genscc.scc_rfcr = SCC_EB;
+ ep->sen_genscc.scc_tfcr = SCC_EB;
+
+ /* Set maximum bytes per receive buffer.
+ * This appears to be an Ethernet frame size, not the buffer
+ * fragment size. It must be a multiple of four.
+ */
+ ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+
+ /* Set CRC preset and mask.
+ */
+ ep->sen_cpres = 0xffffffff;
+ ep->sen_cmask = 0xdebb20e3;
+
+ ep->sen_crcec = 0; /* CRC Error counter */
+ ep->sen_alec = 0; /* alignment error counter */
+ ep->sen_disfc = 0; /* discard frame counter */
+
+ ep->sen_pads = 0x8888; /* Tx short frame pad character */
+ ep->sen_retlim = 15; /* Retry limit threshold */
+
+ ep->sen_maxflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ ep->sen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+
+ ep->sen_maxd1 = PKT_MAXBLR_SIZE; /* maximum DMA1 length */
+ ep->sen_maxd2 = PKT_MAXBLR_SIZE; /* maximum DMA2 length */
+
+ /* Clear hash tables.
+ */
+ ep->sen_gaddr1 = 0;
+ ep->sen_gaddr2 = 0;
+ ep->sen_gaddr3 = 0;
+ ep->sen_gaddr4 = 0;
+ ep->sen_iaddr1 = 0;
+ ep->sen_iaddr2 = 0;
+ ep->sen_iaddr3 = 0;
+ ep->sen_iaddr4 = 0;
+
+ /* Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ */
+ eap = (unsigned char *)&(ep->sen_paddrh);
+ for (i=5; i>=0; i--)
+ *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i];
+
+ ep->sen_pper = 0; /* 'cause the book says so */
+ ep->sen_taddrl = 0; /* temp address (LSB) */
+ ep->sen_taddrm = 0;
+ ep->sen_taddrh = 0; /* temp address (MSB) */
+
+ /* Now allocate the host memory pages and initialize the
+ * buffer descriptors.
+ */
+ bdp = cep->tx_bd_base;
+ for (i=0; i<TX_RING_SIZE; i++) {
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ bdp->cbd_sc = 0;
+ bdp->cbd_bufaddr = 0;
+ bdp++;
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ bdp = cep->rx_bd_base;
+ for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+
+ /* Allocate a page.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+
+ /* Initialize the BD for every fragment in the page.
+ */
+ for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+ bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ mem_addr += CPM_ENET_RX_FRSIZE;
+ bdp++;
+ }
+ }
+
+ /* Set the last buffer to wrap.
+ */
+ bdp--;
+ bdp->cbd_sc |= BD_SC_WRAP;
+
+ /* Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cpmp->cp_cpcr = mk_cr_cmd(CPM_ENET_PAGE, CPM_ENET_BLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ cep->skb_cur = cep->skb_dirty = 0;
+
+ sccp->scc_scce = 0xffff; /* Clear any pending events */
+
+ /* Enable interrupts for transmit error, complete frame
+ * received, and any transmit buffer we have also set the
+ * interrupt flag.
+ */
+ sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+
+ /* Install our interrupt handler.
+ */
+ request_8xxirq(SIU_INT_ENET, scc_enet_interrupt, 0, "enet", dev);
+
+ /* Set GSMR_H to enable all normal operating modes.
+ * Set GSMR_L to enable Ethernet to MC68160.
+ */
+ sccp->scc_gsmrh = 0;
+ sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+
+ /* Set sync/delimiters.
+ */
+ sccp->scc_dsr = 0xd555;
+
+ /* Set processing mode. Use Ethernet CRC, catch broadcast, and
+ * start frame search 22 bit times after RENA.
+ */
+ sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22);
+
+ /* It is now OK to enable the Ethernet transmitter.
+ * Unfortunately, there are board implementation differences here.
+ */
+ io->iop_pparc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_psorc &= ~(PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdirc |= (PC_EST8260_ENET_LOOPBACK |
+ PC_EST8260_ENET_SQE | PC_EST8260_ENET_NOTFD);
+ io->iop_pdatc &= ~(PC_EST8260_ENET_LOOPBACK | PC_EST8260_ENET_SQE);
+ 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;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+
+ /* And last, enable the transmit and receive processing.
+ */
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ printk("%s: SCC ENET Version 0.1, ", dev->name);
+ for (i=0; i<5; i++)
+ printk("%02x:", dev->dev_addr[i]);
+ printk("%02x\n", dev->dev_addr[5]);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * UART driver for MPC8260 CPM SCC or SMC
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc. (source@mvista.com)
+ * 2.3.99 updates
+ *
+ * I used the 8xx uart.c driver as the framework for this driver.
+ * The original code was written for the EST8260 board. I tried to make
+ * it generic, but there may be some assumptions in the structures that
+ * have to be fixed later.
+ *
+ * The 8xx and 8260 are similar, but not identical. Over time we
+ * could probably merge these two drivers.
+ * To save porting time, I did not bother to change any object names
+ * that are not accessed outside of this file.
+ * It still needs lots of work........When it was easy, I included code
+ * to support the SCCs.
+ * Only the SCCs support modem control, so that is not complete either.
+ *
+ * This module exports the following rs232 io functions:
+ *
+ * int rs_8xx_init(void);
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+
+/* this defines the index into rs_table for the port to use
+*/
+#ifndef CONFIG_SERIAL_CONSOLE_PORT
+#define CONFIG_SERIAL_CONSOLE_PORT 0
+#endif
+#endif
+
+#define TX_WAKEUP ASYNC_SHARE_IRQ
+
+static char *serial_name = "CPM UART driver";
+static char *serial_version = "0.01";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+static int serial_console_setup(struct console *co, char *options);
+
+/*
+ * Serial driver configuration section. Here are the various options:
+ */
+#define SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+#define _INLINE_ inline
+
+#define DBG_CNT(s)
+
+/* We overload some of the items in the data structure to meet our
+ * needs. For example, the port address is the CPM parameter ram
+ * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and
+ * 2 SMCs. The "hub6" field is used to indicate the channel number, with
+ * 0 and 1 indicating the SMCs and 2, 3, 4, and 5 are the SCCs.
+ * Since these ports are so versatile, I don't yet have a strategy for
+ * their management. For example, SCC1 is used for Ethernet. Right
+ * now, just don't put them in the table. Of course, right now I just
+ * want the SMC to work as a uart :-)..
+ * The "type" field is currently set to 0, for PORT_UNKNOWN. It is
+ * not currently used. I should probably use it to indicate the port
+ * type of CMS or SCC.
+ * The SMCs do not support any modem control signals.
+ */
+#define smc_scc_num hub6
+
+/* SMC2 is sometimes used for low performance TDM interfaces. Define
+ * this as 1 if you want SMC2 as a serial port UART managed by this driver.
+ * Define this as 0 if you wish to use SMC2 for something else.
+ */
+#define USE_SMC2 1
+
+/* Define SCC to ttySx mapping.
+*/
+#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */
+
+/* Define which SCC is the first one to use for a serial port. These
+ * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used
+ * for Ethernet, and the first available SCC for serial UART is SCC2.
+ * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and
+ * interrupt vectors in the table below to match.
+ */
+#define SCC_IDX_BASE 1 /* table index */
+
+static struct serial_state rs_table[] = {
+ /* UART CLK PORT IRQ FLAGS NUM */
+ { 0, 0, PROFF_SMC1, SIU_INT_SMC1, 0, 0 }, /* SMC1 ttyS0 */
+#if USE_SMC2
+ { 0, 0, PROFF_SMC2, SIU_INT_SMC2, 0, 1 }, /* SMC2 ttyS1 */
+#endif
+ { 0, 0, PROFF_SCC2, SIU_INT_SCC2, 0, SCC_NUM_BASE}, /* SCC2 ttyS2 */
+ { 0, 0, PROFF_SCC3, SIU_INT_SCC3, 0, SCC_NUM_BASE + 1}, /* SCC3 ttyS3 */
+};
+
+#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+/* The number of buffer descriptors and their sizes.
+*/
+#define RX_NUM_FIFO 4
+#define RX_BUF_SIZE 32
+#define TX_NUM_FIFO 4
+#define TX_BUF_SIZE 32
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* The async_struct in serial.h does not really give us what we
+ * need, so define our own here.
+ */
+typedef struct serial_info {
+ int magic;
+ int flags;
+ struct serial_state *state;
+ struct tty_struct *tty;
+ int read_status_mask;
+ int ignore_status_mask;
+ int timeout;
+ int line;
+ int x_char; /* xon/xoff character */
+ int close_delay;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ unsigned long event;
+ unsigned long last_active;
+ int blocked_open; /* # of blocked opens */
+ long session; /* Session of opening process */
+ long pgrp; /* pgrp of opening process */
+ struct tq_struct tqueue;
+ struct tq_struct tqueue_hangup;
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ /* CPM Buffer Descriptor pointers.
+ */
+ cbd_t *rx_bd_base;
+ cbd_t *rx_cur;
+ cbd_t *tx_bd_base;
+ cbd_t *tx_cur;
+} ser_info_t;
+
+static void change_speed(ser_info_t *info);
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static inline int serial_paranoia_check(ser_info_t *info,
+ kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+ static const char *badmagic =
+ "Warning: bad magic number for serial struct (%s) in %s\n";
+ static const char *badinfo =
+ "Warning: null async_struct for (%s) in %s\n";
+
+ if (!info) {
+ printk(badinfo, kdevname(device), routine);
+ return 1;
+ }
+ if (info->magic != SERIAL_MAGIC) {
+ printk(badmagic, kdevname(device), routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts,
+ * indexed by the termio value. The generic CPM functions are responsible
+ * for setting and assigning baud rate generators for us.
+ */
+static int baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_stop(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int idx;
+ unsigned long flags;
+ volatile scc_t *sccp;
+ volatile smc_t *smcp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+ save_flags(flags); cli();
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm &= ~SMCM_TX;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~UART_SCCM_TX;
+ }
+ restore_flags(flags);
+}
+
+static void rs_8xx_start(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int idx;
+ unsigned long flags;
+ volatile scc_t *sccp;
+ volatile smc_t *smcp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_stop"))
+ return;
+
+ save_flags(flags); cli();
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm |= SMCM_TX;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm |= UART_SCCM_TX;
+ }
+ restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines. All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt(). They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off. People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible. After you are done making modifications, it is not a bad
+ * idea to do:
+ *
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(ser_info_t *info,
+ int event)
+{
+ info->event |= 1 << event;
+ queue_task(&info->tqueue, &tq_serial);
+ mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(ser_info_t *info)
+{
+ struct tty_struct *tty = info->tty;
+ unsigned char ch, *cp;
+ /*int ignored = 0;*/
+ int i;
+ ushort status;
+ struct async_icount *icount;
+ volatile cbd_t *bdp;
+
+ icount = &info->state->icount;
+
+ /* Just loop through the closed BDs and copy the characters into
+ * the buffer.
+ */
+ bdp = info->rx_cur;
+ for (;;) {
+ if (bdp->cbd_sc & BD_SC_EMPTY) /* If this one is empty */
+ break; /* we are all done */
+
+ /* The read status mask tell us what we should do with
+ * incoming characters, especially if errors occur.
+ * One special case is the use of BD_SC_EMPTY. If
+ * this is not set, we are supposed to be ignoring
+ * inputs. In this case, just mark the buffer empty and
+ * continue.
+ if (!(info->read_status_mask & BD_SC_EMPTY)) {
+ bdp->cbd_sc |= BD_SC_EMPTY;
+ bdp->cbd_sc &=
+ ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->rx_bd_base;
+ else
+ bdp++;
+ continue;
+ }
+ */
+
+ /* Get the number of characters and the buffer pointer.
+ */
+ i = bdp->cbd_datlen;
+ cp = (unsigned char *)__va(bdp->cbd_bufaddr);
+ status = bdp->cbd_sc;
+
+ /* Check to see if there is room in the tty buffer for
+ * the characters in our BD buffer. If not, we exit
+ * now, leaving the BD with the characters. We'll pick
+ * them up again on the next receive interrupt (which could
+ * be a timeout).
+ */
+ if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
+ break;
+
+ while (i-- > 0) {
+ ch = *cp++;
+ *tty->flip.char_buf_ptr = ch;
+ icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("DR%02x:%02x...", ch, *status);
+#endif
+ *tty->flip.flag_buf_ptr = 0;
+ if (status & (BD_SC_BR | BD_SC_FR |
+ BD_SC_PR | BD_SC_OV)) {
+ /*
+ * For statistics only
+ */
+ if (status & BD_SC_BR)
+ icount->brk++;
+ else if (status & BD_SC_PR)
+ icount->parity++;
+ else if (status & BD_SC_FR)
+ icount->frame++;
+ if (status & BD_SC_OV)
+ icount->overrun++;
+
+ /*
+ * Now check to see if character should be
+ * ignored, and mask off conditions which
+ * should be ignored.
+ if (status & info->ignore_status_mask) {
+ if (++ignored > 100)
+ break;
+ continue;
+ }
+ */
+ status &= info->read_status_mask;
+
+ if (status & (BD_SC_BR)) {
+#ifdef SERIAL_DEBUG_INTR
+ printk("handling break....");
+#endif
+ *tty->flip.flag_buf_ptr = TTY_BREAK;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (status & BD_SC_PR)
+ *tty->flip.flag_buf_ptr = TTY_PARITY;
+ else if (status & BD_SC_FR)
+ *tty->flip.flag_buf_ptr = TTY_FRAME;
+ if (status & BD_SC_OV) {
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+ tty->flip.count++;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ *tty->flip.flag_buf_ptr =
+ TTY_OVERRUN;
+ }
+ }
+ }
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
+
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ }
+
+ /* This BD is ready to be used again. Clear status.
+ * Get next BD.
+ */
+ bdp->cbd_sc |= BD_SC_EMPTY;
+ bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->rx_bd_base;
+ else
+ bdp++;
+ }
+
+ info->rx_cur = (cbd_t *)bdp;
+
+ queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+static _INLINE_ void transmit_chars(ser_info_t *info)
+{
+
+ if (info->flags & TX_WAKEUP) {
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+ }
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("THRE...");
+#endif
+}
+
+#ifdef notdef
+ /* I need to do this for the SCCs, so it is left as a reminder.
+ */
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+ int status;
+ struct async_icount *icount;
+
+ status = serial_in(info, UART_MSR);
+
+ if (status & UART_MSR_ANY_DELTA) {
+ icount = &info->state->icount;
+ /* update input line counters */
+ if (status & UART_MSR_TERI)
+ icount->rng++;
+ if (status & UART_MSR_DDSR)
+ icount->dsr++;
+ if (status & UART_MSR_DDCD) {
+ icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+ if ((info->flags & ASYNC_HARDPPS_CD) &&
+ (status & UART_MSR_DCD))
+ hardpps();
+#endif
+ }
+ if (status & UART_MSR_DCTS)
+ icount->cts++;
+ wake_up_interruptible(&info->delta_msr_wait);
+ }
+
+ if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+ printk("ttys%d CD now %s...", info->line,
+ (status & UART_MSR_DCD) ? "on" : "off");
+#endif
+ if (status & UART_MSR_DCD)
+ wake_up_interruptible(&info->open_wait);
+ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("scheduling hangup...");
+#endif
+ queue_task(&info->tqueue_hangup,
+ &tq_scheduler);
+ }
+ }
+ if (info->flags & ASYNC_CTS_FLOW) {
+ if (info->tty->hw_stopped) {
+ if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+ printk("CTS tx start...");
+#endif
+ info->tty->hw_stopped = 0;
+ info->IER |= UART_IER_THRI;
+ serial_out(info, UART_IER, info->IER);
+ rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+ return;
+ }
+ } else {
+ if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+ printk("CTS tx stop...");
+#endif
+ info->tty->hw_stopped = 1;
+ info->IER &= ~UART_IER_THRI;
+ serial_out(info, UART_IER, info->IER);
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void rs_8xx_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ u_char events;
+ int idx;
+ ser_info_t *info;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ info = (ser_info_t *)dev_id;
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ events = smcp->smc_smce;
+ if (events & SMCM_RX)
+ receive_chars(info);
+ if (events & SMCM_TX)
+ transmit_chars(info);
+ smcp->smc_smce = events;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ events = sccp->scc_scce;
+ if (events & SCCM_RX)
+ receive_chars(info);
+ if (events & SCCM_TX)
+ transmit_chars(info);
+ sccp->scc_scce = events;
+ }
+
+#ifdef SERIAL_DEBUG_INTR
+ printk("rs_interrupt_single(%d, %x)...",
+ info->state->smc_scc_num, events);
+#endif
+#ifdef modem_control
+ check_modem_status(info);
+#endif
+ info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+ printk("end.\n");
+#endif
+}
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+ run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+ ser_info_t *info = (ser_info_t *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred. The path of
+ * hangup processing is:
+ *
+ * serial interrupt routine -> (scheduler tqueue) ->
+ * do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ *
+ */
+static void do_serial_hangup(void *private_)
+{
+ struct async_struct *info = (struct async_struct *) private_;
+ struct tty_struct *tty;
+
+ tty = info->tty;
+ if (!tty)
+ return;
+
+ tty_hangup(tty);
+}
+
+/*static void rs_8xx_timer(void)
+{
+ printk("rs_8xx_timer\n");
+}*/
+
+
+static int startup(ser_info_t *info)
+{
+ unsigned long flags;
+ int retval=0;
+ int idx;
+ struct serial_state *state= info->state;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+ volatile smc_uart_t *up;
+ volatile scc_uart_t *scup;
+
+
+ save_flags(flags); cli();
+
+ if (info->flags & ASYNC_INITIALIZED) {
+ goto errout;
+ }
+
+#ifdef maybe
+ if (!state->port || !state->type) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+ goto errout;
+ }
+#endif
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+
+#ifdef modem_control
+ info->MCR = 0;
+ if (info->tty->termios->c_cflag & CBAUD)
+ info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+#endif
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ /*
+ * and set the speed of the serial port
+ */
+ change_speed(info);
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Enable interrupts and I/O.
+ */
+ smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+ smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+
+ /* We can tune the buffer length and idle characters
+ * to take advantage of the entire incoming buffer size.
+ * If mrblr is something other than 1, maxidl has to be
+ * non-zero or we never get an interrupt. The maxidl
+ * is the number of character times we wait after reception
+ * of the last character before we decide no more characters
+ * are coming.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[state->port];
+#if 0
+ up->smc_mrblr = 1; /* receive buffer length */
+ up->smc_maxidl = 0; /* wait forever for next char */
+#else
+ up->smc_mrblr = RX_BUF_SIZE;
+ up->smc_maxidl = RX_BUF_SIZE;
+#endif
+ up->smc_brkcr = 1; /* number of break chars */
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ scup = (scc_uart_t *)&immr->im_dprambase[state->port];
+#if 0
+ scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */
+ scup->scc_maxidl = 0; /* wait forever for next char */
+#else
+ scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+ scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+ sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ }
+
+ info->flags |= ASYNC_INITIALIZED;
+ restore_flags(flags);
+ return 0;
+
+errout:
+ restore_flags(flags);
+ return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(ser_info_t * info)
+{
+ unsigned long flags;
+ struct serial_state *state;
+ int idx;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("Shutting down serial port %d (irq %d)....", info->line,
+ state->irq);
+#endif
+
+ save_flags(flags); cli(); /* Disable interrupts */
+
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Disable interrupts and I/O.
+ */
+ smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* We can't disable the transmitter if this is the
+ * system console.
+ */
+ if (idx != CONFIG_SERIAL_CONSOLE_PORT)
+#endif
+ smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+ sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+ }
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+ restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(ser_info_t *info)
+{
+ int baud_rate;
+ unsigned cflag, cval, scval, prev_mode;
+ int i, bits, sbits, idx;
+ unsigned long flags;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ cflag = info->tty->termios->c_cflag;
+
+ /* Character length programmed into the mode register is the
+ * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+ * 1 or 2 stop bits, minus 1.
+ * The value 'bits' counts this for us.
+ */
+ cval = 0;
+ scval = 0;
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5: bits = 5; break;
+ case CS6: bits = 6; break;
+ case CS7: bits = 7; break;
+ case CS8: bits = 8; break;
+ /* Never happens, but GCC is too dumb to figure it out */
+ default: bits = 8; break;
+ }
+ sbits = bits - 5;
+
+ if (cflag & CSTOPB) {
+ cval |= SMCMR_SL; /* Two stops */
+ scval |= SCU_PMSR_SL;
+ bits++;
+ }
+ if (cflag & PARENB) {
+ cval |= SMCMR_PEN;
+ scval |= SCU_PMSR_PEN;
+ bits++;
+ }
+ if (!(cflag & PARODD)) {
+ cval |= SMCMR_PM_EVEN;
+ scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
+ }
+
+ /* Determine divisor based on baud rate */
+ i = cflag & CBAUD;
+ if (i >= (sizeof(baud_table)/sizeof(int)))
+ baud_rate = 9600;
+ else
+ baud_rate = baud_table[i];
+
+ info->timeout = (TX_BUF_SIZE*HZ*bits);
+ info->timeout += HZ/50; /* Add .02 seconds of slop */
+
+#ifdef modem_control
+ /* CTS flow control flag and modem status interrupts */
+ info->IER &= ~UART_IER_MSI;
+ if (info->flags & ASYNC_HARDPPS_CD)
+ info->IER |= UART_IER_MSI;
+ if (cflag & CRTSCTS) {
+ info->flags |= ASYNC_CTS_FLOW;
+ info->IER |= UART_IER_MSI;
+ } else
+ info->flags &= ~ASYNC_CTS_FLOW;
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else {
+ info->flags |= ASYNC_CHECK_CD;
+ info->IER |= UART_IER_MSI;
+ }
+ serial_out(info, UART_IER, info->IER);
+#endif
+
+ /*
+ * Set up parity check flag
+ */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+ info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= BD_SC_FR | BD_SC_PR;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= BD_SC_BR;
+
+ /*
+ * Characters to ignore
+ */
+ info->ignore_status_mask = 0;
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= BD_SC_BR;
+ /*
+ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= BD_SC_OV;
+ }
+ /*
+ * !!! ignore all characters if CREAD is not set
+ */
+ if ((cflag & CREAD) == 0)
+ info->read_status_mask &= ~BD_SC_EMPTY;
+ save_flags(flags); cli();
+
+ /* Start bit has not been added (so don't, because we would just
+ * subtract it later), and we need to add one for the number of
+ * stops bits (there is always at least one).
+ */
+ bits++;
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+
+ /* Set the mode register. We want to keep a copy of the
+ * enables, because we want to put them back if they were
+ * present.
+ */
+ prev_mode = smcp->smc_smcmr;
+ smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
+ smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_pmsr = (sbits << 12) | scval;
+ }
+
+ m8260_cpm_setbrg(info->state->smc_scc_num, baud_rate);
+
+ restore_flags(flags);
+}
+
+static void rs_8xx_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+ return;
+
+ if (!tty)
+ return;
+
+ bdp = info->tx_cur;
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ *((char *)__va(bdp->cbd_bufaddr)) = ch;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+
+ info->tx_cur = (cbd_t *)bdp;
+
+}
+
+static int rs_8xx_write(struct tty_struct * tty, int from_user,
+ const unsigned char *buf, int count)
+{
+ int c, ret = 0;
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write"))
+ return 0;
+
+ if (!tty)
+ return 0;
+
+ bdp = info->tx_cur;
+
+ while (1) {
+ c = MIN(count, TX_BUF_SIZE);
+
+ if (c <= 0)
+ break;
+
+ if (bdp->cbd_sc & BD_SC_READY) {
+ info->flags |= TX_WAKEUP;
+ break;
+ }
+
+ if (from_user) {
+ if (c !=
+ copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
+ } else {
+ memcpy(__va(bdp->cbd_bufaddr), buf, c);
+ }
+
+ bdp->cbd_datlen = c;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ buf += c;
+ count -= c;
+ ret += c;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+ info->tx_cur = (cbd_t *)bdp;
+ }
+ return ret;
+}
+
+static int rs_8xx_write_room(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int ret;
+
+ if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+ return 0;
+
+ if ((info->tx_cur->cbd_sc & BD_SC_READY) == 0) {
+ info->flags &= ~TX_WAKEUP;
+ ret = TX_BUF_SIZE;
+ }
+ else {
+ info->flags |= TX_WAKEUP;
+ ret = 0;
+ }
+ return ret;
+}
+
+/* I could track this with transmit counters....maybe later.
+*/
+static int rs_8xx_chars_in_buffer(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+ return 0;
+ return 0;
+}
+
+static void rs_8xx_flush_buffer(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+ return;
+
+ /* There is nothing to "flush", whatever we gave the CPM
+ * is on its way out.
+ */
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ info->flags &= ~TX_WAKEUP;
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
+{
+ volatile cbd_t *bdp;
+
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+ return;
+
+ bdp = info->tx_cur;
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ *((char *)__va(bdp->cbd_bufaddr)) = ch;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ /* Get next BD.
+ */
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = info->tx_bd_base;
+ else
+ bdp++;
+
+ info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ *
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_throttle(struct tty_struct * tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("throttle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+ return;
+
+ if (I_IXOFF(tty))
+ rs_8xx_send_xchar(tty, STOP_CHAR(tty));
+
+#ifdef modem_control
+ if (tty->termios->c_cflag & CRTSCTS)
+ info->MCR &= ~UART_MCR_RTS;
+
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+}
+
+static void rs_8xx_unthrottle(struct tty_struct * tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+ char buf[64];
+
+ printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+ tty->ldisc.chars_in_buffer(tty));
+#endif
+
+ if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+ return;
+
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ rs_8xx_send_xchar(tty, START_CHAR(tty));
+ }
+#ifdef modem_control
+ if (tty->termios->c_cflag & CRTSCTS)
+ info->MCR |= UART_MCR_RTS;
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+#ifdef maybe
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * is emptied. On bus types like RS485, the transmitter must
+ * release the bus after transmitting. This must be done when
+ * the transmit shift register is empty, not be done when the
+ * transmit holding register is empty. This functionality
+ * allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+ unsigned char status;
+ unsigned int result;
+
+ cli();
+ status = serial_in(info, UART_LSR);
+ sti();
+ result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+ return put_user(result,value);
+}
+#endif
+
+static int get_modem_info(ser_info_t *info, unsigned int *value)
+{
+ unsigned int result = 0;
+#ifdef modem_control
+ unsigned char control, status;
+
+ control = info->MCR;
+ cli();
+ status = serial_in(info, UART_MSR);
+ sti();
+ result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+ | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+ | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+ | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+ | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
+ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
+ | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
+ | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+#endif
+ return put_user(result,value);
+}
+
+static int set_modem_info(ser_info_t *info, unsigned int cmd,
+ unsigned int *value)
+{
+ int error;
+ unsigned int arg;
+
+ error = get_user(arg, value);
+ if (error)
+ return error;
+#ifdef modem_control
+ switch (cmd) {
+ case TIOCMBIS:
+ if (arg & TIOCM_RTS)
+ info->MCR |= UART_MCR_RTS;
+ if (arg & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+ if (arg & TIOCM_OUT1)
+ info->MCR |= UART_MCR_OUT1;
+ if (arg & TIOCM_OUT2)
+ info->MCR |= UART_MCR_OUT2;
+#endif
+ break;
+ case TIOCMBIC:
+ if (arg & TIOCM_RTS)
+ info->MCR &= ~UART_MCR_RTS;
+ if (arg & TIOCM_DTR)
+ info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+ if (arg & TIOCM_OUT1)
+ info->MCR &= ~UART_MCR_OUT1;
+ if (arg & TIOCM_OUT2)
+ info->MCR &= ~UART_MCR_OUT2;
+#endif
+ break;
+ case TIOCMSET:
+ info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+ UART_MCR_OUT1 |
+ UART_MCR_OUT2 |
+#endif
+ UART_MCR_DTR))
+ | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+ | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+ | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+ | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+ break;
+ default:
+ return -EINVAL;
+ }
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+#endif
+ return 0;
+}
+
+/* Sending a break is a two step process on the SMC/SCC. It is accomplished
+ * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT
+ * command. We take advantage of the begin/end functions to make this
+ * happen.
+ */
+static void begin_break(ser_info_t *info)
+{
+ volatile cpm8260_t *cp;
+ uint page, sblock;
+ ushort num;
+
+ cp = cpmp;
+
+ if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ if (num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+ }
+ else {
+ num -= SCC_NUM_BASE;
+ switch (num) {
+ case 0:
+ page = CPM_CR_SCC1_PAGE;
+ sblock = CPM_CR_SCC1_SBLOCK;
+ break;
+ case 1:
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ break;
+ case 2:
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ break;
+ case 3:
+ page = CPM_CR_SCC4_PAGE;
+ sblock = CPM_CR_SCC4_SBLOCK;
+ break;
+ default: return;
+ }
+ }
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_STOP_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+static void end_break(ser_info_t *info)
+{
+ volatile cpm8260_t *cp;
+ uint page, sblock;
+ ushort num;
+
+ cp = cpmp;
+
+ if ((num = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ if (num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+ }
+ else {
+ num -= SCC_NUM_BASE;
+ switch (num) {
+ case 0:
+ page = CPM_CR_SCC1_PAGE;
+ sblock = CPM_CR_SCC1_SBLOCK;
+ break;
+ case 1:
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ break;
+ case 2:
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ break;
+ case 3:
+ page = CPM_CR_SCC4_PAGE;
+ sblock = CPM_CR_SCC4_SBLOCK;
+ break;
+ default: return;
+ }
+ }
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break(ser_info_t *info, int duration)
+{
+ current->state = TASK_INTERRUPTIBLE;
+#ifdef SERIAL_DEBUG_SEND_BREAK
+ printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
+#endif
+ begin_break(info);
+ schedule_timeout(duration);
+ end_break(info);
+#ifdef SERIAL_DEBUG_SEND_BREAK
+ printk("done jiffies=%lu\n", jiffies);
+#endif
+}
+
+
+static int rs_8xx_ioctl(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ int error;
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ int retval;
+ struct async_icount cnow; /* kernel counter temps */
+ struct serial_icounter_struct *p_cuser; /* user space */
+
+ if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+ return -ENODEV;
+
+ if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case TCSBRK: /* SVID version: non-zero arg --> no break */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ if (!arg) {
+ send_break(info, HZ/4); /* 1/4 second */
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ return 0;
+ case TCSBRKP: /* support for POSIX tcsendbreak() */
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (signal_pending(current))
+ return -EINTR;
+ send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ if (signal_pending(current))
+ return -EINTR;
+ return 0;
+ case TIOCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ begin_break(info);
+ return 0;
+ case TIOCCBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ end_break(info);
+ return 0;
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
+ case TIOCSSOFTCAR:
+ error = get_user(arg, (unsigned int *) arg);
+ if (error)
+ return error;
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+ 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);
+#ifdef maybe
+ case TIOCSERGETLSR: /* Get line status register */
+ return get_lsr_info(info, (unsigned int *) arg);
+#endif
+ /*
+ * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+ case TIOCMIWAIT:
+#ifdef modem_control
+ cli();
+ /* note the counters on entry */
+ cprev = info->state->icount;
+ sti();
+ while (1) {
+ interruptible_sleep_on(&info->delta_msr_wait);
+ /* see if a signal did it */
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cli();
+ cnow = info->state->icount; /* atomic copy */
+ sti();
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ /* NOTREACHED */
+#else
+ return 0;
+#endif
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+ case TIOCGICOUNT:
+ cli();
+ cnow = info->state->icount;
+ sti();
+ p_cuser = (struct serial_icounter_struct *) arg;
+ error = put_user(cnow.cts, &p_cuser->cts);
+ if (error) return error;
+ error = put_user(cnow.dsr, &p_cuser->dsr);
+ if (error) return error;
+ error = put_user(cnow.rng, &p_cuser->rng);
+ if (error) return error;
+ error = put_user(cnow.dcd, &p_cuser->dcd);
+ if (error) return error;
+ return 0;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/* FIX UP modem control here someday......
+*/
+static void rs_8xx_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+
+ if ( (tty->termios->c_cflag == old_termios->c_cflag)
+ && ( RELEVANT_IFLAG(tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag)))
+ return;
+
+ change_speed(info);
+
+#ifdef modem_control
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) &&
+ !(tty->termios->c_cflag & CBAUD)) {
+ info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ (tty->termios->c_cflag & CBAUD)) {
+ info->MCR |= UART_MCR_DTR;
+ if (!tty->hw_stopped ||
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ info->MCR |= UART_MCR_RTS;
+ }
+ cli();
+ serial_out(info, UART_MCR, info->MCR);
+ sti();
+ }
+
+ /* Handle turning off CRTSCTS */
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ rs_8xx_start(tty);
+ }
+#endif
+
+#if 0
+ /*
+ * No need to wake up processes in open wait, since they
+ * sample the CLOCAL flag once, and don't recheck it.
+ * XXX It's not clear whether the current behavior is correct
+ * or not. Hence, this may change.....
+ */
+ if (!(old_termios->c_cflag & CLOCAL) &&
+ (tty->termios->c_cflag & CLOCAL))
+ wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_8xx_close(struct tty_struct *tty, struct file * filp)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ struct serial_state *state;
+ unsigned long flags;
+ int idx;
+ volatile smc_t *smcp;
+ volatile scc_t *sccp;
+
+ if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+ return;
+
+ state = info->state;
+
+ save_flags(flags); cli();
+
+ if (tty_hung_up_p(filp)) {
+ DBG_CNT("before DEC-hung");
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+ return;
+ }
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+ if ((tty->count == 1) && (state->count != 1)) {
+ /*
+ * Uh, oh. tty->count is 1, which means that the tty
+ * structure will be freed. state->count should always
+ * be one in these conditions. If it's greater than
+ * one, we've got real problems, since it means the
+ * serial port won't be shutdown.
+ */
+ printk("rs_close: bad serial port count; tty->count is 1, "
+ "state->count is %d\n", state->count);
+ state->count = 1;
+ }
+ if (--state->count < 0) {
+ printk("rs_close: bad serial port count for ttys%d: %d\n",
+ info->line, state->count);
+ state->count = 0;
+ }
+ if (state->count) {
+ DBG_CNT("before DEC-2");
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+ return;
+ }
+ info->flags |= ASYNC_CLOSING;
+ /*
+ * Save the termios structure, since this port may have
+ * separate termios for callout and dialin.
+ */
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ info->state->normal_termios = *tty->termios;
+ if (info->flags & ASYNC_CALLOUT_ACTIVE)
+ info->state->callout_termios = *tty->termios;
+ /*
+ * Now we wait for the transmit buffer to clear; and we notify
+ * the line discipline to only process XON/XOFF characters.
+ */
+ tty->closing = 1;
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, info->closing_wait);
+ /*
+ * At this point we stop accepting input. To do this, we
+ * disable the receive line status interrupts, and tell the
+ * interrupt driver to stop checking the data ready bit in the
+ * line status register.
+ */
+ info->read_status_mask &= ~BD_SC_EMPTY;
+ if (info->flags & ASYNC_INITIALIZED) {
+ if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
+ smcp = &immr->im_smc[idx];
+ smcp->smc_smcm &= ~SMCM_RX;
+ smcp->smc_smcmr &= ~SMCMR_REN;
+ }
+ else {
+ sccp = &immr->im_scc[idx - SCC_IDX_BASE];
+ sccp->scc_sccm &= ~UART_SCCM_RX;
+ sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
+ }
+ /*
+ * Before we drop DTR, make sure the UART transmitter
+ * has completely drained; this is especially
+ * important if there is a transmit FIFO!
+ */
+ rs_8xx_wait_until_sent(tty, info->timeout);
+ }
+ shutdown(info);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ info->event = 0;
+ info->tty = 0;
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(info->close_delay);
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+ ASYNC_CLOSING);
+ wake_up_interruptible(&info->close_wait);
+ MOD_DEC_USE_COUNT;
+ restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+ /*int lsr;*/
+ volatile cbd_t *bdp;
+
+ if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+ return;
+
+#ifdef maybe
+ if (info->state->type == PORT_UNKNOWN)
+ return;
+#endif
+
+ orig_jiffies = jiffies;
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = 1;
+ if (timeout)
+ char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk("jiff=%lu...", jiffies);
+#endif
+
+ /* We go through the loop at least once because we can't tell
+ * exactly when the last character exits the shifter. There can
+ * be at least two characters waiting to be sent after the buffers
+ * are empty.
+ */
+ do {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+ current->state = TASK_INTERRUPTIBLE;
+/* current->counter = 0; make us low-priority */
+ schedule_timeout(char_time);
+ if (signal_pending(current))
+ break;
+ if (timeout && ((orig_jiffies + timeout) < jiffies))
+ break;
+ bdp = info->tx_cur;
+ } while (bdp->cbd_sc & BD_SC_READY);
+ current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+ printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_8xx_hangup(struct tty_struct *tty)
+{
+ ser_info_t *info = (ser_info_t *)tty->driver_data;
+ struct serial_state *state = info->state;
+
+ if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+ return;
+
+ state = info->state;
+
+ rs_8xx_flush_buffer(tty);
+ shutdown(info);
+ info->event = 0;
+ state->count = 0;
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+ info->tty = 0;
+ wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+ ser_info_t *info)
+{
+#ifdef DO_THIS_LATER
+ DECLARE_WAITQUEUE(wait, current);
+#endif
+ struct serial_state *state = info->state;
+ int retval;
+ int do_clocal = 0;
+
+ /*
+ * 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) ||
+ (info->flags & ASYNC_CLOSING)) {
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+#else
+ return -EAGAIN;
+#endif
+ }
+
+ /*
+ * If this is a callout device, then just make sure the normal
+ * device isn't being used.
+ */
+ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+ if (info->flags & ASYNC_NORMAL_ACTIVE)
+ return -EBUSY;
+ if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_SESSION_LOCKOUT) &&
+ (info->session != current->session))
+ return -EBUSY;
+ if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (info->flags & ASYNC_PGRP_LOCKOUT) &&
+ (info->pgrp != current->pgrp))
+ return -EBUSY;
+ info->flags |= ASYNC_CALLOUT_ACTIVE;
+ return 0;
+ }
+
+ /*
+ * If non-blocking mode is set, or the port is not enabled,
+ * then make the check up front and then exit.
+ * If this is an SMC port, we don't have modem control to wait
+ * for, so just get out here.
+ */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR)) ||
+ (info->state->smc_scc_num < SCC_NUM_BASE)) {
+ if (info->flags & ASYNC_CALLOUT_ACTIVE)
+ return -EBUSY;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+ if (state->normal_termios.c_cflag & CLOCAL)
+ do_clocal = 1;
+ } else {
+ 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, state->count is dropped by one, so that
+ * rs_close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+ retval = 0;
+#ifdef DO_THIS_LATER
+ add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready before block: ttys%d, count = %d\n",
+ state->line, state->count);
+#endif
+ cli();
+ if (!tty_hung_up_p(filp))
+ state->count--;
+ sti();
+ info->blocked_open++;
+ while (1) {
+ cli();
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (tty->termios->c_cflag & CBAUD))
+ serial_out(info, UART_MCR,
+ serial_inp(info, UART_MCR) |
+ (UART_MCR_DTR | UART_MCR_RTS));
+ sti();
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (tty_hung_up_p(filp) ||
+ !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+ if (info->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#else
+ retval = -EAGAIN;
+#endif
+ break;
+ }
+ if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+ !(info->flags & ASYNC_CLOSING) &&
+ (do_clocal || (serial_in(info, UART_MSR) &
+ UART_MSR_DCD)))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready blocking: ttys%d, count = %d\n",
+ info->line, state->count);
+#endif
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&info->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ state->count++;
+ info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+ printk("block_til_ready after blocking: ttys%d, count = %d\n",
+ info->line, state->count);
+#endif
+#endif /* DO_THIS_LATER */
+ if (retval)
+ return retval;
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+}
+
+static int get_async_struct(int line, ser_info_t **ret_info)
+{
+ struct serial_state *sstate;
+
+ sstate = rs_table + line;
+ if (sstate->info) {
+ sstate->count++;
+ *ret_info = (ser_info_t *)sstate->info;
+ return 0;
+ }
+ else {
+ return -ENOMEM;
+ }
+}
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_8xx_open(struct tty_struct *tty, struct file * filp)
+{
+ ser_info_t *info;
+ int retval, line;
+
+ line = MINOR(tty->device) - tty->driver.minor_start;
+ if ((line < 0) || (line >= NR_PORTS))
+ return -ENODEV;
+ retval = get_async_struct(line, &info);
+ if (retval)
+ return retval;
+ if (serial_paranoia_check(info, tty->device, "rs_open"))
+ return -ENODEV;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+ info->state->count);
+#endif
+ tty->driver_data = info;
+ info->tty = tty;
+
+ /*
+ * Start up serial port
+ */
+ retval = startup(info);
+ if (retval)
+ return retval;
+
+ MOD_INC_USE_COUNT;
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open returning after block_til_ready with %d\n",
+ retval);
+#endif
+ return retval;
+ }
+
+ if ((info->state->count == 1) &&
+ (info->flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = info->state->normal_termios;
+ else
+ *tty->termios = info->state->callout_termios;
+ change_speed(info);
+ }
+
+ info->session = current->session;
+ info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+ printk("rs_open ttys%d successful...", info->line);
+#endif
+ return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static int inline line_info(char *buf, struct serial_state *state)
+{
+#ifdef notdef
+ struct async_struct *info = state->info, scr_info;
+ char stat_buf[30], control, status;
+#endif
+ int ret;
+
+ ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+ state->line,
+ (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC",
+ state->port, state->irq);
+
+ if (!state->port || (state->type == PORT_UNKNOWN)) {
+ ret += sprintf(buf+ret, "\n");
+ return ret;
+ }
+
+#ifdef notdef
+ /*
+ * Figure out the current RS-232 lines
+ */
+ if (!info) {
+ info = &scr_info; /* This is just for serial_{in,out} */
+
+ info->magic = SERIAL_MAGIC;
+ info->port = state->port;
+ info->flags = state->flags;
+ info->quot = 0;
+ info->tty = 0;
+ }
+ cli();
+ status = serial_in(info, UART_MSR);
+ control = info ? info->MCR : serial_in(info, UART_MCR);
+ sti();
+
+ stat_buf[0] = 0;
+ stat_buf[1] = 0;
+ if (control & UART_MCR_RTS)
+ strcat(stat_buf, "|RTS");
+ if (status & UART_MSR_CTS)
+ strcat(stat_buf, "|CTS");
+ if (control & UART_MCR_DTR)
+ strcat(stat_buf, "|DTR");
+ if (status & UART_MSR_DSR)
+ strcat(stat_buf, "|DSR");
+ if (status & UART_MSR_DCD)
+ strcat(stat_buf, "|CD");
+ if (status & UART_MSR_RI)
+ strcat(stat_buf, "|RI");
+
+ if (info->quot) {
+ ret += sprintf(buf+ret, " baud:%d",
+ state->baud_base / info->quot);
+ }
+
+ ret += sprintf(buf+ret, " tx:%d rx:%d",
+ state->icount.tx, state->icount.rx);
+
+ if (state->icount.frame)
+ ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+
+ if (state->icount.parity)
+ ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+
+ if (state->icount.brk)
+ ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
+
+ if (state->icount.overrun)
+ ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+ /*
+ * Last thing is the RS-232 status lines
+ */
+ ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+#endif
+ return ret;
+}
+
+int rs_8xx_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int i, len = 0;
+ off_t begin = 0;
+
+ len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+ for (i = 0; i < NR_PORTS && len < 4000; i++) {
+ len += line_info(page + len, &rs_table[i]);
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ }
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (begin-off);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_serial_version(void)
+{
+ printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+}
+
+
+/*
+ * The serial console driver used during boot. Note that these names
+ * clash with those found in "serial.c", so we currently can't support
+ * the 16xxx uarts and these at the same time. I will fix this to become
+ * an indirect function call from tty_io.c (or something).
+ */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * Print a string to the serial port trying not to disturb any possible
+ * real use of the port...
+ */
+static void serial_console_write(struct console *c, const char *s,
+ unsigned count)
+{
+ struct serial_state *ser;
+ ser_info_t *info;
+ unsigned i;
+ volatile cbd_t *bdp, *bdbase;
+ volatile smc_uart_t *up;
+ volatile u_char *cp;
+
+ ser = rs_table + c->index;
+
+ /* If the port has been initialized for general use, we have
+ * to use the buffer descriptors allocated there. Otherwise,
+ * we simply use the single buffer allocated.
+ */
+ if ((info = (ser_info_t *)ser->info) != NULL) {
+ bdp = info->tx_cur;
+ bdbase = info->tx_bd_base;
+ }
+ else {
+ /* Pointer to UART in parameter ram.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[ser->port];
+
+ /* Get the address of the host memory buffer.
+ */
+ bdp = bdbase = (cbd_t *)&immr->im_dprambase[up->smc_tbase];
+ }
+
+ /*
+ * We need to gracefully shut down the transmitter, disable
+ * interrupts, then send our bytes out.
+ */
+
+ /*
+ * Now, do each character. This is not as bad as it looks
+ * since this is a holding FIFO and not a transmitting FIFO.
+ * We could add the complexity of filling the entire transmit
+ * buffer, but we would just wait longer between accesses......
+ */
+ for (i = 0; i < count; i++, s++) {
+ /* Wait for transmitter fifo to empty.
+ * Ready indicates output is ready, and xmt is doing
+ * that, not that it is ready for us to send.
+ */
+ while (bdp->cbd_sc & BD_SC_READY);
+ /* Send the character out. */
+ cp = __va(bdp->cbd_bufaddr);
+ *cp = *s;
+
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP)
+ bdp = bdbase;
+ else
+ bdp++;
+
+ /* if a LF, also do CR... */
+ if (*s == 10) {
+ while (bdp->cbd_sc & BD_SC_READY);
+ cp = __va(bdp->cbd_bufaddr);
+ *cp = 13;
+ bdp->cbd_datlen = 1;
+ bdp->cbd_sc |= BD_SC_READY;
+
+ if (bdp->cbd_sc & BD_SC_WRAP) {
+ bdp = bdbase;
+ }
+ else {
+ bdp++;
+ }
+ }
+ }
+
+ /*
+ * Finally, Wait for transmitter & holding register to empty
+ * and restore the IER
+ */
+ while (bdp->cbd_sc & BD_SC_READY);
+
+ if (info)
+ info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * Receive character from the serial port. This only works well
+ * before the port is initialize for real use.
+ */
+static int serial_console_wait_key(struct console *co)
+{
+ struct serial_state *ser;
+ u_char c, *cp;
+ ser_info_t *info;
+ volatile cbd_t *bdp;
+ volatile smc_uart_t *up;
+
+ ser = rs_table + co->index;
+
+ /* Pointer to UART in parameter ram.
+ */
+ up = (smc_uart_t *)&immr->im_dprambase[ser->port];
+
+ /* Get the address of the host memory buffer.
+ * If the port has been initialized for general use, we must
+ * use information from the port structure.
+ */
+ if ((info = (ser_info_t *)ser->info))
+ bdp = info->rx_cur;
+ else
+ bdp = (cbd_t *)&immr->im_dprambase[up->smc_rbase];
+
+ /*
+ * We need to gracefully shut down the receiver, disable
+ * interrupts, then read the input.
+ */
+ while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */
+ cp = __va(bdp->cbd_bufaddr);
+
+ if (info) {
+ if (bdp->cbd_sc & BD_SC_WRAP) {
+ bdp = info->rx_bd_base;
+ }
+ else {
+ bdp++;
+ }
+ info->rx_cur = (cbd_t *)bdp;
+ }
+
+ c = *cp;
+ return((int)c);
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+ return MKDEV(TTYAUX_MAJOR, 64 + c->index);
+}
+
+
+static struct console sercons = {
+ "ttyS",
+ serial_console_write,
+ NULL,
+ serial_console_device,
+ serial_console_wait_key,
+ NULL,
+ serial_console_setup,
+ CON_PRINTBUFFER,
+ CONFIG_SERIAL_CONSOLE_PORT,
+ 0,
+ NULL
+};
+
+/*
+ * Register console.
+ */
+long __init console_8xx_init(long kmem_start, long kmem_end)
+{
+ register_console(&sercons);
+ return kmem_start;
+}
+
+#endif
+
+/* Default console baud rate as determined by the board information
+ * structure.
+ */
+static int baud_idx;
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+int __init rs_8xx_init(void)
+{
+ struct serial_state * state;
+ ser_info_t *info;
+ uint mem_addr, dp_addr;
+ int i, j, idx;
+ uint page, sblock;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile scc_t *scp;
+ volatile scc_uart_t *sup;
+ volatile immap_t *immap;
+ volatile iop8260_t *io;
+
+ init_bh(SERIAL_BH, do_serial_bh);
+#if 0
+ timer_table[RS_TIMER].fn = rs_8xx_timer;
+ timer_table[RS_TIMER].expires = 0;
+#endif
+
+ show_serial_version();
+
+ /* Initialize the tty_driver structure */
+
+ /*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
+ __clear_user(&serial_driver,sizeof(struct tty_driver));
+ serial_driver.magic = TTY_DRIVER_MAGIC;
+ serial_driver.driver_name = "serial";
+ serial_driver.name = "ttyS";
+ serial_driver.major = TTY_MAJOR;
+ serial_driver.minor_start = 64;
+ serial_driver.num = NR_PORTS;
+ serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver.subtype = SERIAL_TYPE_NORMAL;
+ serial_driver.init_termios = tty_std_termios;
+ serial_driver.init_termios.c_cflag =
+ baud_idx | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver.flags = TTY_DRIVER_REAL_RAW;
+ serial_driver.refcount = &serial_refcount;
+ serial_driver.table = serial_table;
+ serial_driver.termios = serial_termios;
+ serial_driver.termios_locked = serial_termios_locked;
+
+ serial_driver.open = rs_8xx_open;
+ serial_driver.close = rs_8xx_close;
+ serial_driver.write = rs_8xx_write;
+ serial_driver.put_char = rs_8xx_put_char;
+ serial_driver.write_room = rs_8xx_write_room;
+ serial_driver.chars_in_buffer = rs_8xx_chars_in_buffer;
+ serial_driver.flush_buffer = rs_8xx_flush_buffer;
+ serial_driver.ioctl = rs_8xx_ioctl;
+ serial_driver.throttle = rs_8xx_throttle;
+ serial_driver.unthrottle = rs_8xx_unthrottle;
+ serial_driver.send_xchar = rs_8xx_send_xchar;
+ serial_driver.set_termios = rs_8xx_set_termios;
+ serial_driver.stop = rs_8xx_stop;
+ serial_driver.start = rs_8xx_start;
+ serial_driver.hangup = rs_8xx_hangup;
+ serial_driver.wait_until_sent = rs_8xx_wait_until_sent;
+ serial_driver.read_proc = rs_8xx_read_proc;
+
+ /*
+ * The callout device is just like normal device except for
+ * major number and the subtype code.
+ */
+ callout_driver = serial_driver;
+ callout_driver.name = "cua";
+ callout_driver.major = TTYAUX_MAJOR;
+ callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+ callout_driver.read_proc = 0;
+ callout_driver.proc_entry = 0;
+
+ if (tty_register_driver(&serial_driver))
+ panic("Couldn't register serial driver\n");
+ if (tty_register_driver(&callout_driver))
+ panic("Couldn't register callout driver\n");
+
+ immap = immr;
+ cp = &immap->im_cpm;
+ io = &immap->im_ioport;
+
+ /* This should have been done long ago by the early boot code,
+ * but do it again to make sure.
+ */
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+ /* Geeze, here we go....Picking I/O port bits....Lots of
+ * choices. If you don't like mine, pick your own.
+ * Configure SMCs Tx/Rx. SMC1 is only on Port D, SMC2 is
+ * only on Port A. You either pick 'em, or not.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+#if USE_SMC2
+ io->iop_ppara |= 0x01800000;
+ io->iop_pdira |= 0x00800000;
+ io->iop_pdira &= ~0x01000000;
+ io->iop_psora &= ~0x01800000;
+#endif
+
+ /* Configure SCC2 and SCC3. Be careful about the fine print.
+ * Secondary options are only available when you take away
+ * the primary option. Unless the pins are used for something
+ * else, SCC2 and SCC3 are on Port B.
+ * Port B, 8 - SCC3 TxD
+ * Port B, 12 - SCC2 TxD
+ * Port B, 14 - SCC3 RxD
+ * Port B, 15 - SCC2 RxD
+ */
+ io->iop_pparb |= 0x008b0000;
+ io->iop_pdirb |= 0x00880000;
+ io->iop_psorb |= 0x00880000;
+ io->iop_pdirb &= ~0x00030000;
+ io->iop_psorb &= ~0x00030000;
+
+ /* Wire BRG1 to SMC1 and BRG2 to SMC2.
+ */
+ immap->im_cpmux.cmx_smr = 0;
+
+ /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and
+ * BRG4 to SCC3.
+ */
+ immap->im_cpmux.cmx_scr &= ~0x00ffff00;
+ immap->im_cpmux.cmx_scr |= 0x00121b00;
+
+ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+ state->magic = SSTATE_MAGIC;
+ state->line = i;
+ state->type = PORT_UNKNOWN;
+ state->custom_divisor = 0;
+ state->close_delay = 5*HZ/10;
+ state->closing_wait = 30*HZ;
+ state->callout_termios = callout_driver.init_termios;
+ state->normal_termios = serial_driver.init_termios;
+ state->icount.cts = state->icount.dsr =
+ state->icount.rng = state->icount.dcd = 0;
+ state->icount.rx = state->icount.tx = 0;
+ state->icount.frame = state->icount.parity = 0;
+ state->icount.overrun = state->icount.brk = 0;
+ printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
+ i, state->port,
+ (state->smc_scc_num < SCC_NUM_BASE) ? "SMC" : "SCC");
+#ifdef CONFIG_SERIAL_CONSOLE
+ /* If we just printed the message on the console port, and
+ * we are about to initialize it for general use, we have
+ * to wait a couple of character times for the CR/NL to
+ * make it out of the transmit buffer.
+ */
+ if (i == CONFIG_SERIAL_CONSOLE_PORT)
+ mdelay(2);
+#endif
+ info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
+ if (info) {
+ /*memset(info, 0, sizeof(ser_info_t));*/
+ __clear_user(info,sizeof(ser_info_t));
+ info->magic = SERIAL_MAGIC;
+ info->flags = state->flags;
+ info->tqueue.routine = do_softint;
+ info->tqueue.data = info;
+ info->tqueue_hangup.routine = do_serial_hangup;
+ info->tqueue_hangup.data = info;
+ info->line = i;
+ info->state = state;
+ state->info = (struct async_struct *)info;
+
+ /* We need to allocate a transmit and receive buffer
+ * descriptors from dual port ram, and a character
+ * buffer area from host mem.
+ */
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+
+ /* Allocate space for FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
+
+ for (j=0; j<(RX_NUM_FIFO-1); j++) {
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+ mem_addr += RX_BUF_SIZE;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+ if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+ sp = &immap->im_smc[idx];
+ up = (smc_uart_t *)&immap->im_dprambase[state->port];
+ up->smc_rbase = dp_addr;
+ }
+ else {
+ scp = &immap->im_scc[idx - SCC_IDX_BASE];
+ sup = (scc_uart_t *)&immap->im_dprambase[state->port];
+ sup->scc_genscc.scc_rbase = dp_addr;
+ }
+
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+
+ /* Allocate space for FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
+
+ for (j=0; j<(TX_NUM_FIFO-1); j++) {
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = BD_SC_INTRPT;
+ mem_addr += TX_BUF_SIZE;
+ bdp++;
+ }
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
+
+ if (idx < SCC_NUM_BASE) {
+ up->smc_tbase = dp_addr;
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+ up->smc_brkcr = 1;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 0) {
+ page = CPM_CR_SMC1_PAGE;
+ sblock = CPM_CR_SMC1_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SMC2_PAGE;
+ sblock = CPM_CR_SMC2_SBLOCK;
+ }
+
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+ }
+ else {
+ sup->scc_genscc.scc_tbase = dp_addr;
+
+ /* Set up the uart parameters in the
+ * parameter ram.
+ */
+ sup->scc_genscc.scc_rfcr = SMC_EB;
+ sup->scc_genscc.scc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single
+ * character interrupts. Using idle charater
+ * time requires some additional tuning.
+ */
+ sup->scc_genscc.scc_mrblr = 1;
+ sup->scc_maxidl = 0;
+ sup->scc_brkcr = 1;
+ sup->scc_parec = 0;
+ sup->scc_frmec = 0;
+ sup->scc_nosec = 0;
+ sup->scc_brkec = 0;
+ sup->scc_uaddr1 = 0;
+ sup->scc_uaddr2 = 0;
+ sup->scc_toseq = 0;
+ sup->scc_char1 = 0x8000;
+ sup->scc_char2 = 0x8000;
+ sup->scc_char3 = 0x8000;
+ sup->scc_char4 = 0x8000;
+ sup->scc_char5 = 0x8000;
+ sup->scc_char6 = 0x8000;
+ sup->scc_char7 = 0x8000;
+ sup->scc_char8 = 0x8000;
+ sup->scc_rccm = 0xc0ff;
+
+ /* Send the CPM an initialize command.
+ */
+ if (state->smc_scc_num == 2) {
+ page = CPM_CR_SCC2_PAGE;
+ sblock = CPM_CR_SCC2_SBLOCK;
+ }
+ else {
+ page = CPM_CR_SCC3_PAGE;
+ sblock = CPM_CR_SCC3_SBLOCK;
+ }
+
+ cp->cp_cpcr = mk_cr_cmd(page, sblock, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ scp->scc_gsmrh = 0;
+ scp->scc_gsmrl =
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ /* Disable all interrupts and clear all pending
+ * events.
+ */
+ scp->scc_sccm = 0;
+ scp->scc_scce = 0xffff;
+ scp->scc_dsr = 0x7e7e;
+ scp->scc_pmsr = 0x3000;
+ }
+
+ /* Install interrupt handler.
+ */
+ request_8xxirq(state->irq, rs_8xx_interrupt, 0, "uart", info);
+
+ /* Set up the baud rate generator.
+ */
+ m8260_cpm_setbrg(state->smc_scc_num,
+ baud_table[baud_idx]);
+
+ /* If the port is the console, enable Rx and Tx.
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+ if (i == CONFIG_SERIAL_CONSOLE_PORT)
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+#endif
+ }
+ }
+ return 0;
+}
+
+/* This must always be called before the rs_8xx_init() function, otherwise
+ * it blows away the port control information.
+*/
+static int __init serial_console_setup(struct console *co, char *options)
+{
+ struct serial_state *ser;
+ uint mem_addr, dp_addr, bidx;
+ volatile cbd_t *bdp;
+ volatile cpm8260_t *cp;
+ volatile immap_t *immap;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile iop8260_t *io;
+ bd_t *bd;
+
+ bd = (bd_t *)__res;
+
+ for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++)
+ if (bd->bi_baudrate == baud_table[bidx])
+ break;
+
+ co->cflag = CREAD|CLOCAL|bidx|CS8;
+ baud_idx = bidx;
+
+ ser = rs_table + co->index;
+
+
+ immap = immr;
+ cp = &immap->im_cpm;
+ io = &immap->im_ioport;
+
+ /* This should have been done long ago by the early boot code,
+ * but do it again to make sure.
+ */
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ *(ushort *)(&immap->im_dprambase[PROFF_SMC2_BASE]) = PROFF_SMC2;
+
+ /* Right now, assume we are using SMCs.
+ */
+ sp = &immap->im_smc[ser->smc_scc_num];
+
+ /* When we get here, the CPM has been reset, so we need
+ * to configure the port.
+ * We need to allocate a transmit and receive buffer descriptor
+ * from dual port ram, and a character buffer area from host mem.
+ */
+ up = (smc_uart_t *)&immap->im_dprambase[ser->port];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Use Port D for SMC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ */
+ dp_addr = m8260_cpm_dpalloc(sizeof(cbd_t) * 2);
+
+ /* Allocate space for two 2 byte FIFOs in the host memory.
+ */
+ mem_addr = m8260_cpm_hostalloc(4);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ bdp = (cbd_t *)&immap->im_dprambase[dp_addr];
+ bdp->cbd_bufaddr = __pa(mem_addr);
+ (bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+
+ /* For the receive, set empty and wrap.
+ * For transmit, set wrap.
+ */
+ bdp->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ (bdp+1)->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dp_addr; /* Base of receive buffer desc. */
+ up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set this to 1 for now, so we get single character interrupts.
+ */
+ up->smc_mrblr = 1; /* receive buffer length */
+ up->smc_maxidl = 0; /* wait forever for next char */
+
+ /* Send the CPM an initialize command.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Set up the baud rate generator.
+ */
+ m8260_cpm_setbrg(ser->smc_scc_num, bd->bi_baudrate);
+
+ /* And finally, enable Rx and Tx.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return 0;
+}
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/spinlock.h>
#include <asm/8xx_immap.h>
#include <asm/pgtable.h>
* Port C, 9 (CTS2) - SCC Ethernet Collision
*/
+/* The transmitter timeout
+ */
+#define TX_TIMEOUT (2*HZ)
+
/* The number of Tx and Rx buffers. These are allocated from the page
* pool. The code may assume these are power of two, so it is best
* to keep them that size.
* empty and completely full conditions. The empty/ready indicator in
* the buffer descriptor determines the actual condition.
*/
-struct cpm_enet_private {
+struct scc_enet_private {
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
ushort skb_cur;
scc_t *sccp;
struct net_device_stats stats;
uint tx_full;
- uint tx_busy;
- unsigned long lock;
- int interrupt;
+ spinlock_t lock;
};
-static int cpm_enet_open(struct net_device *dev);
-static int cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int cpm_enet_rx(struct net_device *dev);
-static void cpm_enet_interrupt(void *dev_id);
-static int cpm_enet_close(struct net_device *dev);
-static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev);
+static int scc_enet_open(struct net_device *dev);
+static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int scc_enet_rx(struct net_device *dev);
+static void scc_enet_interrupt(void *dev_id);
+static int scc_enet_close(struct net_device *dev);
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/* Get this from various configuration locations (depends on board).
#endif
static int
-cpm_enet_open(struct net_device *dev)
+scc_enet_open(struct net_device *dev)
{
/* I should reset the ring buffers here, but I don't yet know
}
static int
-cpm_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
volatile cbd_t *bdp;
- unsigned long flags;
-
- /* Transmitter timeout, serious problems. */
- if (cep->tx_busy) {
- int tickssofar = jiffies - dev->trans_start;
- if (tickssofar < 200)
- return 1;
- printk("%s: transmit timed out.\n", dev->name);
- cep->stats.tx_errors++;
-#ifndef final_version
- {
- int i;
- cbd_t *bdp;
- printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
- cep->cur_tx, cep->tx_full ? " (full)" : "",
- cep->cur_rx);
- bdp = cep->tx_bd_base;
- for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- bdp = cep->rx_bd_base;
- for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
- printk("%04x %04x %08x\n",
- bdp->cbd_sc,
- bdp->cbd_datlen,
- bdp->cbd_bufaddr);
- }
-#endif
-
- cep->tx_busy=0;
- dev->trans_start = jiffies;
-
- return 0;
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- * done with atomic_swap(1, cep->tx_busy), but set_bit() works as well.
- */
- if (test_and_set_bit(0, (void*)&cep->tx_busy) != 0) {
- printk("%s: Transmitter access conflict.\n", dev->name);
- return 1;
- }
-
- if (test_and_set_bit(0, (void*)&cep->lock) != 0) {
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear cep->tx_busy flag. */
- return 1;
- }
/* Fill in a Tx ring entry */
bdp = cep->cur_tx;
* This should not happen, since cep->tx_busy should be set.
*/
printk("%s: tx queue full!.\n", dev->name);
- cep->lock = 0;
return 1;
}
#endif
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- flush_dcache_range(skb->data, skb->data + skb->len);
+ flush_dcache_range((unsigned long)(skb->data),
+ (unsigned long)(skb->data + skb->len));
+
+ spin_lock_irq(&cep->lock);
/* Send it on its way. Tell CPM its ready, interrupt when done,
* its the last BD of the frame, and to put the CRC on the end.
else
bdp++;
- save_flags(flags);
- cli();
- cep->lock = 0;
if (bdp->cbd_sc & BD_ENET_TX_READY)
- cep->tx_full = 1;
- else
- cep->tx_busy=0;
- restore_flags(flags);
+ netif_stop_queue(dev);
cep->cur_tx = (cbd_t *)bdp;
+ spin_unlock_irq(&cep->lock);
+
return 0;
}
+static void
+scc_enet_timeout(struct net_device *dev)
+{
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
+
+ printk("%s: transmit timed out.\n", dev->name);
+ cep->stats.tx_errors++;
+#ifndef final_version
+ {
+ int i;
+ cbd_t *bdp;
+ printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n",
+ cep->cur_tx, cep->tx_full ? " (full)" : "",
+ cep->cur_rx);
+ bdp = cep->tx_bd_base;
+ for (i = 0 ; i < TX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ bdp = cep->rx_bd_base;
+ for (i = 0 ; i < RX_RING_SIZE; i++, bdp++)
+ printk("%04x %04x %08x\n",
+ bdp->cbd_sc,
+ bdp->cbd_datlen,
+ bdp->cbd_bufaddr);
+ }
+#endif
+ if (!cep->tx_full)
+ netif_wake_queue(dev);
+}
+
/* The interrupt handler.
* This is called from the CPM handler, not the MPC core interrupt.
*/
static void
-cpm_enet_interrupt(void *dev_id)
+scc_enet_interrupt(void *dev_id)
{
struct net_device *dev = dev_id;
- volatile struct cpm_enet_private *cep;
+ volatile struct scc_enet_private *cep;
volatile cbd_t *bdp;
ushort int_events;
int must_restart;
- cep = (struct cpm_enet_private *)dev->priv;
- if (cep->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
- cep->interrupt = 1;
+ cep = (struct scc_enet_private *)dev->priv;
/* Get the interrupt events that caused us to be here.
*/
/* Handle receive event in its own function.
*/
if (int_events & SCCE_ENET_RXF)
- cpm_enet_rx(dev_id);
+ scc_enet_rx(dev_id);
/* Check for a transmit error. The manual is a little unclear
* about this, so the debug code until I get it figured out. It
/* Transmit OK, or non-fatal error. Update the buffer descriptors.
*/
if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+ spin_lock(&cep->lock);
bdp = cep->dirty_tx;
while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
if ((bdp==cep->cur_tx) && (cep->tx_full == 0))
/* Since we have freed up a buffer, the ring is no longer
* full.
*/
- if (cep->tx_full && cep->tx_busy) {
- cep->tx_full = 0;
- cep->tx_busy = 0;
- netif_wake_queue(dev);
+ if (cep->tx_full) {
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
}
cep->dirty_tx = (cbd_t *)bdp;
mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG;
while (cp->cp_cpcr & CPM_CR_FLG);
}
+ spin_unlock(&cep->lock);
}
/* Check for receive busy, i.e. packets coming but no place to
printk("CPM ENET: BSY can't happen.\n");
}
- cep->interrupt = 0;
-
return;
}
* effectively tossing the packet.
*/
static int
-cpm_enet_rx(struct net_device *dev)
+scc_enet_rx(struct net_device *dev)
{
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
volatile cbd_t *bdp;
struct sk_buff *skb;
ushort pkt_len;
- cep = (struct cpm_enet_private *)dev->priv;
+ cep = (struct scc_enet_private *)dev->priv;
/* First, grab all of the stats for the incoming packet.
* These get messed up if we get called due to a busy condition.
}
static int
-cpm_enet_close(struct net_device *dev)
+scc_enet_close(struct net_device *dev)
{
/* Don't know what to do yet.
*/
return 0;
}
-static struct net_device_stats *cpm_enet_get_stats(struct net_device *dev)
+static struct net_device_stats *scc_enet_get_stats(struct net_device *dev)
{
- struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+ struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv;
return &cep->stats;
}
static void set_multicast_list(struct net_device *dev)
{
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
struct dev_mc_list *dmi;
u_char *mcptr, *tdptr;
volatile scc_enet_t *ep;
int i, j;
- cep = (struct cpm_enet_private *)dev->priv;
+ cep = (struct scc_enet_private *)dev->priv;
/* Get pointer to SCC area in parameter RAM.
*/
* transmit and receive to make sure we don't catch the CPM with some
* inconsistent control information.
*/
-int __init cpm_enet_init(void)
+int __init scc_enet_init(void)
{
struct net_device *dev;
- struct cpm_enet_private *cep;
+ struct scc_enet_private *cep;
int i, j;
unsigned char *eap;
unsigned long mem_addr;
/* Allocate some private information.
*/
- cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+ cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
/*memset(cep, 0, sizeof(*cep));*/
__clear_user(cep,sizeof(*cep));
+ spin_lock_init(&cep->lock);
/* Create an Ethernet device instance.
*/
*/
pte = find_pte(&init_mm, mem_addr);
pte_val(*pte) |= _PAGE_NO_CACHE;
- flush_tlb_page(current->mm->mmap, mem_addr);
+ flush_tlb_page(init_mm.mmap, mem_addr);
/* Initialize the BD for every fragment in the page.
*/
/* Install our interrupt handler.
*/
- cpm_install_handler(CPMVEC_ENET, cpm_enet_interrupt, dev);
+ cpm_install_handler(CPMVEC_ENET, scc_enet_interrupt, dev);
/* Set GSMR_H to enable all normal operating modes.
* Set GSMR_L to enable Ethernet to MC68160.
#endif
/* The CPM Ethernet specific entries in the device structure. */
- dev->open = cpm_enet_open;
- dev->hard_start_xmit = cpm_enet_start_xmit;
- dev->stop = cpm_enet_close;
- dev->get_stats = cpm_enet_get_stats;
+ dev->open = scc_enet_open;
+ dev->hard_start_xmit = scc_enet_start_xmit;
+ dev->tx_timeout = scc_enet_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->stop = scc_enet_close;
+ dev->get_stats = scc_enet_get_stats;
dev->set_multicast_list = set_multicast_list;
/* And last, enable the transmit and receive processing.
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
#include "commproc.h"
+
+#ifdef CONFIG_KGDB
+extern int kgdb_output_string (const char* s, unsigned int count);
+#endif
#ifdef CONFIG_SERIAL_CONSOLE
#include <linux/console.h>
* are coming.
*/
up = (smc_uart_t *)&cpmp->cp_dparam[state->port];
-#if 0
- up->smc_mrblr = 1; /* receive buffer length */
- up->smc_maxidl = 0; /* wait forever for next char */
-#else
+
up->smc_mrblr = RX_BUF_SIZE;
up->smc_maxidl = RX_BUF_SIZE;
-#endif
+
up->smc_brkcr = 1; /* number of break chars */
}
else {
sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
scup = (scc_uart_t *)&cpmp->cp_dparam[state->port];
-#if 0
- scup->scc_genscc.scc_mrblr = 1; /* receive buffer length */
- scup->scc_maxidl = 0; /* wait forever for next char */
-#else
+
scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
scup->scc_maxidl = RX_BUF_SIZE;
-#endif
sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
ser_info_t *info = (ser_info_t *)tty->driver_data;
volatile cbd_t *bdp;
+#ifdef CONFIG_KGDB
+ /* Try to let stub handle output. Returns true if it did. */
+ if (kgdb_output_string(buf, count))
+ return ret;
+#endif
+
if (serial_paranoia_check(info, tty->device, "rs_write"))
return 0;
}
if (from_user) {
- if (c !=
- copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
+ c -= copy_from_user(__va(bdp->cbd_bufaddr), buf, c);
+ if (!c) {
if (!ret)
ret = -EFAULT;
break;
* Print a string to the serial port trying not to disturb any possible
* real use of the port...
*/
-static void serial_console_write(struct console *c, const char *s,
+static void my_console_write(int idx, const char *s,
unsigned count)
{
struct serial_state *ser;
volatile smc_uart_t *up;
volatile u_char *cp;
- ser = rs_table + c->index;
+ ser = rs_table + idx;
/* If the port has been initialized for general use, we have
* to use the buffer descriptors allocated there. Otherwise,
* that, not that it is ready for us to send.
*/
while (bdp->cbd_sc & BD_SC_READY);
- /* Send the character out. */
- cp = __va(bdp->cbd_bufaddr);
+
+ /* Send the character out.
+ * If the buffer address is in the CPM DPRAM, don't
+ * convert it.
+ */
+ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
+ cp = (u_char *)(bdp->cbd_bufaddr);
+ else
+ cp = __va(bdp->cbd_bufaddr);
*cp = *s;
bdp->cbd_datlen = 1;
info->tx_cur = (cbd_t *)bdp;
}
+static void serial_console_write(struct console *c, const char *s,
+ unsigned count)
+{
+#ifdef CONFIG_KGDB
+ /* Try to let stub handle output. Returns true if it did. */
+ if (kgdb_output_string(s, count))
+ return;
+#endif
+ my_console_write(c->index, s, count);
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_write(const char *s, unsigned count)
+{
+ my_console_write(0, s, count);
+ return(count);
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void
+putDebugChar(char ch)
+{
+ my_console_write(0, &ch, 1);
+}
+#endif
+
/*
* Receive character from the serial port. This only works well
* before the port is initialize for real use.
*/
-static int serial_console_wait_key(struct console *co)
+static int my_console_wait_key(int idx, int xmon, char *obuf)
{
struct serial_state *ser;
u_char c, *cp;
ser_info_t *info;
volatile cbd_t *bdp;
volatile smc_uart_t *up;
+ int i;
- ser = rs_table + co->index;
+ ser = rs_table + idx;
/* Pointer to UART in parameter ram.
*/
/*
* We need to gracefully shut down the receiver, disable
* interrupts, then read the input.
+ * XMON just wants a poll. If no character, return -1, else
+ * return the character.
+ */
+ if (!xmon) {
+ while (bdp->cbd_sc & BD_SC_EMPTY);
+ }
+ else {
+ if (bdp->cbd_sc & BD_SC_EMPTY)
+ return -1;
+ }
+
+ /* If the buffer address is in the CPM DPRAM, don't
+ * convert it.
*/
- while (bdp->cbd_sc & BD_SC_EMPTY); /* Wait for a character */
- cp = __va(bdp->cbd_bufaddr);
+ if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
+ cp = (u_char *)(bdp->cbd_bufaddr);
+ else
+ cp = __va(bdp->cbd_bufaddr);
+
+ if (obuf) {
+ i = c = bdp->cbd_datlen;
+ while (i-- > 0)
+ *obuf++ = *cp++;
+ }
+ else {
+ c = *cp;
+ }
+ bdp->cbd_sc |= BD_SC_EMPTY;
if (info) {
if (bdp->cbd_sc & BD_SC_WRAP) {
info->rx_cur = (cbd_t *)bdp;
}
- c = *cp;
return((int)c);
}
+static int serial_console_wait_key(struct console *co)
+{
+ return(my_console_wait_key(co->index, 0, NULL));
+}
+
+#ifdef CONFIG_XMON
+int
+xmon_8xx_read_poll(void)
+{
+ return(my_console_wait_key(0, 1, NULL));
+}
+
+int
+xmon_8xx_read_char(void)
+{
+ return(my_console_wait_key(0, 0, NULL));
+}
+#endif
+
+#ifdef CONFIG_KGDB
+static char kgdb_buf[RX_BUF_SIZE], *kgdp;
+static int kgdb_chars;
+
+unsigned char
+getDebugChar(void)
+{
+ if (kgdb_chars <= 0) {
+ kgdb_chars = my_console_wait_key(0, 0, kgdb_buf);
+ kgdp = kgdb_buf;
+ }
+ kgdb_chars--;
+
+ return(*kgdp++);
+}
+
+void kgdb_interruptible(int state)
+{
+}
+void kgdb_map_scc(void)
+{
+ struct serial_state *ser;
+ uint mem_addr;
+ volatile cbd_t *bdp;
+ volatile smc_uart_t *up;
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+ /* To avoid data cache CPM DMA coherency problems, allocate a
+ * buffer in the CPM DPRAM. This will work until the CPM and
+ * serial ports are initialized. At that time a memory buffer
+ * will be allcoated.
+ * The port is already initialized from the boot procedure, all
+ * we do here is give it a different buffer and make it a FIFO.
+ */
+
+ ser = rs_table;
+
+ /* Right now, assume we are using SMCs.
+ */
+ up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
+
+ /* Allocate space for an input FIFO, plus a few bytes for output.
+ * Allocate bytes to maintain word alignment.
+ */
+ mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+ bdp->cbd_bufaddr = mem_addr;
+
+ bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+ bdp->cbd_bufaddr = mem_addr+RX_BUF_SIZE;
+
+ up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
+ up->smc_maxidl = RX_BUF_SIZE;
+}
+#endif
+
static kdev_t serial_console_device(struct console *c)
{
return MKDEV(TTYAUX_MAJOR, 64 + c->index);
* character interrupts. Using idle charater
* time requires some additional tuning.
*/
- up->smc_mrblr = 1;
- up->smc_maxidl = 0;
+ up->smc_mrblr = RX_BUF_SIZE;
+ up->smc_maxidl = RX_BUF_SIZE;
up->smc_brkcr = 1;
/* Send the CPM an initialize command.
sup->scc_genscc.scc_rfcr = SMC_EB;
sup->scc_genscc.scc_tfcr = SMC_EB;
- /* Set this to 1 for now, so we get single
- * character interrupts. Using idle charater
- * time requires some additional tuning.
- */
- sup->scc_genscc.scc_mrblr = 1;
- sup->scc_maxidl = 0;
+ sup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+ sup->scc_maxidl = RX_BUF_SIZE;
sup->scc_brkcr = 1;
sup->scc_parec = 0;
sup->scc_frmec = 0;
#endif
}
}
+
return 0;
}
*/
dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2);
- /* Allocate space for two 2 byte FIFOs in the host memory.
- */
- mem_addr = m8xx_cpm_hostalloc(4);
+ /* Allocate space for an input FIFO, plus a few bytes for output.
+ * Allocate bytes to maintain word alignment.
+ */
+ mem_addr = m8xx_cpm_hostalloc(RX_BUF_SIZE + 4);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
*/
bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
bdp->cbd_bufaddr = __pa(mem_addr);
- (bdp+1)->cbd_bufaddr = __pa(mem_addr+2);
+ (bdp+1)->cbd_bufaddr = __pa(mem_addr+RX_BUF_SIZE);
/* For the receive, set empty and wrap.
* For transmit, set wrap.
up->smc_rfcr = SMC_EB;
up->smc_tfcr = SMC_EB;
- /* Set this to 1 for now, so we get single character interrupts.
- */
- up->smc_mrblr = 1; /* receive buffer length */
- up->smc_maxidl = 0; /* wait forever for next char */
+ up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */
+ up->smc_maxidl = RX_BUF_SIZE;
/* Send the CPM an initialize command.
*/
LINKFLAGS = -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
CPPFLAGS := $(CPPFLAGS) -D__powerpc__
CFLAGS := $(CFLAGS) -D__powerpc__ -fsigned-char \
- -msoft-float -pipe -fno-builtin -ffixed-r2 -Wno-uninitialized \
+ -msoft-float -pipe -ffixed-r2 -Wno-uninitialized \
-mmultiple -mstring
CPP = $(CC) -E $(CFLAGS)
DRIVERS += arch/ppc/8xx_io/8xx_io.a
endif
+ifdef CONFIG_8260
+SUBDIRS += arch/ppc/8260_io
+DRIVERS += arch/ppc/8260_io/8260_io.a
+endif
+
ifdef CONFIG_APUS
SUBDIRS += arch/ppc/amiga
ARCHIVES += arch/ppc/amiga/amiga.o
endif
ifdef CONFIG_6xx
+ifndef CONFIG_8260
$(BOOT_TARGETS): $(CHECKS) vmlinux
@$(MAKECOFFBOOT) $@
@$(MAKEBOOT) $@
@$(MAKECOFFBOOT) $@
@$(MAKEBOOT) $@
@$(MAKECHRPBOOT) $@
+else
+# 8260 is custom 6xx
+$(BOOT_TARGETS): $(CHECKS) vmlinux
+ @$(MAKECOFFBOOT) $@
+ @$(MAKEMBXBOOT) $@
+endif
endif
ifdef CONFIG_PPC64
"6xx/7xx/7400 CONFIG_6xx \
4xx CONFIG_4xx \
630/Power3(64-Bit) CONFIG_PPC64 \
- 82xx CONFIG_82xx \
+ 8260 CONFIG_8260 \
8xx CONFIG_8xx" 6xx
+if [ "$CONFIG_8260" = "y" ]; then
+ define_bool CONFIG_6xx y
+ define_bool CONFIG_SERIAL_CONSOLE y
+fi
+
if [ "$CONFIG_4xx" = "y" ]; then
choice 'Machine Type' \
"Oak CONFIG_OAK \
choice 'Machine Type' \
"PowerMac/PReP/MTX/CHRP CONFIG_ALL_PPC \
Gemini CONFIG_GEMINI \
+ EST8260 CONFIG_EST8260 \
APUS CONFIG_APUS" PowerMac/PReP/MTX/CHRP
fi
define_bool CONFIG_ALL_PPC y
fi
+if [ "$CONFIG_8xx" = "y" -o "$CONFIG_8260" = "y" ]; then
+ define_bool CONFIG_ALL_PPC n
+fi
+
bool 'Symmetric multi-processing support' CONFIG_SMP
if [ "$CONFIG_6xx" = "y" ];then
bool 'AltiVec Support' CONFIG_ALTIVEC
define_bool CONFIG_SBUS n
if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \
- "$CONFIG_82xx" = "y" ]; then
+ "$CONFIG_8260" = "y" ]; then
define_bool CONFIG_PCI n
else
if [ "$CONFIG_6xx" = "y" -o "$CONFIG_PPC64" = "y" ]; then
bool 'Support for ADB mouse' CONFIG_ADBMOUSE
fi
bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
- bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
fi
source net/ax25/Config.in
+source net/irda/Config.in
+
mainmenu_option next_comment
comment 'ISDN subsystem'
source arch/ppc/8xx_io/Config.in
fi
+if [ "$CONFIG_8260" = "y" ]; then
+source arch/ppc/8260_io/Config.in
+fi
+
source drivers/usb/Config.in
mainmenu_option next_comment
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-# CONFIG_PREP is not set
-CONFIG_CHRP=y
-# CONFIG_ALL_PPC is not set
-# CONFIG_APUS is not set
-# CONFIG_MBX is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
-CONFIG_PCI=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
-# CONFIG_PARPORT is not set
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-# CONFIG_PMAC_PBOOK is not set
-CONFIG_MAC_KEYBOARD=y
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADBMOUSE is not set
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
-# CONFIG_TOTALMP is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
-CONFIG_BLK_DEV_SL82C105=y
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=10
-CONFIG_SCSI_MAC53C94=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
-CONFIG_DEC_ELCP=y
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_RADIO is not set
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_IMSTT=y
-# CONFIG_FB_CT65550 is not set
-# CONFIG_FB_S3TRIO is not set
-CONFIG_FB_VGA=y
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-CONFIG_FBCON_VGA=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-CONFIG_NVRAM=y
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-CONFIG_MAC_PARTITION=y
-# CONFIG_NLS is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
# CONFIG_UID16 is not set
#
# General setup
#
-# CONFIG_PCI is not set
-CONFIG_PCI=y
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
CONFIG_PCI=y
CONFIG_NET=y
CONFIG_SYSCTL=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_PCI_NAMES is not set
# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
#
# Parallel port support
CONFIG_PMAC_PBOOK=y
CONFIG_MAC_FLOPPY=y
CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_MACIO=y
CONFIG_ADB_KEYBOARD=y
CONFIG_ADBMOUSE=y
CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
# Plug and Play configuration
#
# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_STRIPED is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_IP_MROUTE is not set
CONFIG_IP_ALIAS=y
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
-
-#
-#
-#
# CONFIG_IPX is not set
CONFIG_ATALK=m
# CONFIG_DECNET is not set
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
# CONFIG_BLK_DEV_IDEDMA_PCI is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
# CONFIG_BLK_DEV_IDEDMA is not set
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_CMD64X_RAID is not set
# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_HPT366_FIP is not set
+# CONFIG_HPT366_MODE3 is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_MASTER is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# SCSI support
#
CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
#
# CONFIG_FTAPE is not set
# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
-#
-# USB support
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=y
-CONFIG_USB_MOUSE=y
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_MIX is not set
-# CONFIG_INPUT_MOUSEDEV_DIGITIZER is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
#
# File systems
#
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
# Sound
#
CONFIG_SOUND=y
+CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_SSCAPE is not set
# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
# CONFIG_SOUND_VMIDI is not set
# CONFIG_SOUND_TRIX is not set
# CONFIG_SOUND_MSS is not set
# CONFIG_SOUND_NM256 is not set
# CONFIG_SOUND_MAD16 is not set
# CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
# CONFIG_SOUND_PSS is not set
# CONFIG_SOUND_SOFTOSS is not set
# CONFIG_SOUND_SB is not set
# CONFIG_SOUND_UART6850 is not set
# CONFIG_SOUND_AEDSP16 is not set
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_DSBR is not set
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_WMFORCE is not set
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
#
# Kernel hacking
#
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
-# CONFIG_8xx is not set
-CONFIG_PMAC=y
-# CONFIG_PREP is not set
-# CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
-# CONFIG_GEMINI is not set
-# CONFIG_APUS is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-CONFIG_6xx=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-CONFIG_PCI=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=m
-CONFIG_HOTPLUG=y
-
-#
-# PCMCIA/Cardbus support
-#
-CONFIG_PCMCIA=m
-CONFIG_CARDBUS=y
-# CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FB=y
-CONFIG_FB_COMPAT_XPMAC=y
-CONFIG_PMAC_PBOOK=y
-CONFIG_MAC_FLOPPY=y
-CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADB=y
-CONFIG_ADB_CUDA=y
-CONFIG_ADB_MACIO=y
-CONFIG_ADB_PMU=y
-CONFIG_ADB_KEYBOARD=y
-CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
-CONFIG_BOOTX_TEXT=y
-# CONFIG_MOTOROLA_HOTSWAP is not set
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDEFLOPPY=y
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-CONFIG_IDEDMA_PCI_AUTO=y
-CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
-CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-CONFIG_BLK_DEV_CMD646=y
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-# CONFIG_BLK_DEV_PDC202XX is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_IDEDMA_PMAC_AUTO=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_CPQ_DA is not set
-
-#
-# Additional Block Devices
-#
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-CONFIG_BLK_DEV_IDE_MODES=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK=y
-# CONFIG_RTNETLINK is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-CONFIG_IP_ALIAS=y
-# CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_KHTTPD is not set
-# CONFIG_ATM is not set
-
-#
-#
-#
-# CONFIG_IPX is not set
-CONFIG_ATALK=m
-# CONFIG_DECNET is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-CONFIG_AIC7XXX_PROC_STATS=y
-CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_SYM53C8XX is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=5
-CONFIG_SCSI_MAC53C94=y
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MACE=y
-CONFIG_BMAC=y
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_SIS900 is not set
-# CONFIG_DM9102 is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
-# CONFIG_ACENIC is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_DEC_ELCP is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE3210 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_LTPC is not set
-# CONFIG_COPS is not set
-# CONFIG_IPDDP is not set
-CONFIG_PPP=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring driver support
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# PCMCIA network devices
-#
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-
-#
-# Frame-buffer support
-#
-CONFIG_FB=y
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
-CONFIG_FB_OF=y
-CONFIG_FB_CONTROL=y
-CONFIG_FB_PLATINUM=y
-CONFIG_FB_VALKYRIE=y
-CONFIG_FB_IMSTT=y
-CONFIG_FB_CT65550=y
-# CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-CONFIG_FBCON_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-CONFIG_FONT_SUN8x16=y
-CONFIG_FONT_SUN12x22=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=m
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# Mice
-#
-CONFIG_BUSMOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_LOGIBUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_ADBMOUSE=y
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-
-#
-# USB drivers - not for the faint of heart
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-CONFIG_USB_OHCI=y
-CONFIG_USB_OHCI_DEBUG=y
-# CONFIG_USB_OHCI_HCD is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEBUG_ISOC=y
-CONFIG_USB_PROC=y
-# CONFIG_USB_EZUSB is not set
-
-#
-# USB Devices
-#
-CONFIG_USB_HUB=y
-CONFIG_USB_MOUSE=y
-CONFIG_USB_HP_SCANNER=m
-CONFIG_USB_KBD=y
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
-# CONFIG_USB_USS720 is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVPTS_FS=y
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
-# CONFIG_NCP_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_OSF_PARTITION is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_NLS is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-CONFIG_DMASOUND=y
-# CONFIG_SOUND_CMPCI is not set
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-# CONFIG_SOUND_OSS is not set
-
-#
-# Kernel hacking
-#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+++ /dev/null
-#
-# Automatically generated by make menuconfig: don't edit
-#
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_6xx=y
-# CONFIG_8xx is not set
-# CONFIG_PMAC is not set
-CONFIG_PREP=y
-# CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
-# CONFIG_APUS is not set
-# CONFIG_MBX is not set
-# CONFIG_SMP is not set
-CONFIG_MACH_SPECIFIC=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-CONFIG_PCI=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
-CONFIG_NET=y
-CONFIG_SYSCTL=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
-# CONFIG_PARPORT is not set
-# CONFIG_FB is not set
-CONFIG_VGA_CONSOLE=y
-# CONFIG_PMAC_PBOOK is not set
-# CONFIG_MAC_KEYBOARD is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_MAC_SERIAL is not set
-# CONFIG_ADBMOUSE is not set
-# CONFIG_PROC_DEVICETREE is not set
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-# CONFIG_IDE_CHIPSETS is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
-# CONFIG_FILTER is not set
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_RARP is not set
-# CONFIG_IP_NOSR is not set
-CONFIG_SKB_LARGE=y
-# CONFIG_IPV6 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_LLC is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# SCSI support
-#
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-CONFIG_SCSI_NCR53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
-# CONFIG_SCSI_MAC53C94 is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_NET_VENDOR_3COM is not set
-CONFIG_LANCE=y
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
-CONFIG_PCNET32=y
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
-CONFIG_DE4X5=y
-# CONFIG_DEC_ELCP is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_LNE390 is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_TLAN is not set
-# CONFIG_ES3210 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_ZNET is not set
-# CONFIG_NET_POCKET is not set
-# CONFIG_FDDI is not set
-# CONFIG_DLCI is not set
-CONFIG_PPP=m
-# CONFIG_SLIP is not set
-# CONFIG_NET_RADIO is not set
-# CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_NLS=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_KOI8_R is not set
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-# CONFIG_SOUND_ES1370 is not set
-# CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_SONICVIBES is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
-# CONFIG_SOUND_SSCAPE is not set
-# CONFIG_SOUND_TRIX is not set
-# CONFIG_SOUND_MAD16 is not set
-# CONFIG_SOUND_WAVEFRONT is not set
-CONFIG_SOUND_CS4232=y
-CONFIG_CS4232_BASE=530
-CONFIG_CS4232_IRQ=11
-CONFIG_CS4232_DMA=0
-CONFIG_CS4232_DMA2=3
-CONFIG_CS4232_MPU_BASE=330
-CONFIG_CS4232_MPU_IRQ=9
-# CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
-# CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
-# CONFIG_SOUND_UART6850 is not set
-
-#
-# Additional low level sound drivers
-#
-# CONFIG_LOWLEVEL_SOUND is not set
#
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
#
# CONFIG_UID16 is not set
CONFIG_ADB_KEYBOARD=y
CONFIG_ADBMOUSE=y
CONFIG_PROC_DEVICETREE=y
-# CONFIG_TOTALMP is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_MOTOROLA_HOTSWAP is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_STRIPED is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_IP_MROUTE is not set
CONFIG_IP_ALIAS=y
CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
CONFIG_SKB_LARGE=y
# CONFIG_IPV6 is not set
# CONFIG_KHTTPD is not set
# CONFIG_ATM is not set
-
-#
-#
-#
# CONFIG_IPX is not set
CONFIG_ATALK=m
# CONFIG_DECNET is not set
# IDE, ATA and ATAPI Block devices
#
CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
# CONFIG_BLK_DEV_CMD640 is not set
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
# CONFIG_BLK_DEV_ISAPNP is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
# CONFIG_BLK_DEV_SL82C105 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# SCSI support
#
CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
# CONFIG_SCSI_DEBUG_QUEUES is not set
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_CONSTANTS=y
CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
CONFIG_AIC7XXX_PROC_STATS=y
CONFIG_AIC7XXX_RESET_DELAY=15
-# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_MESH=y
CONFIG_SCSI_MESH_SYNC_RATE=5
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
# CONFIG_DRM_TDFX is not set
# CONFIG_AGP is not set
-#
-# USB support
-#
-CONFIG_USB=y
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_SCANNER is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=y
-CONFIG_USB_MOUSE=y
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-CONFIG_INPUT_KEYBDEV=y
-CONFIG_INPUT_MOUSEDEV=y
-# CONFIG_INPUT_MOUSEDEV_MIX is not set
-# CONFIG_INPUT_MOUSEDEV_DIGITIZER is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
#
# File systems
#
CONFIG_AUTOFS_FS=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_MINIX_FS is not set
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
#
# Partition Types
# Sound
#
CONFIG_SOUND=y
+CONFIG_DMASOUND_AWACS=y
CONFIG_DMASOUND=y
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_ES1370 is not set
CONFIG_SOUND_CS4232=m
# CONFIG_SOUND_SSCAPE is not set
# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
# CONFIG_SOUND_VMIDI is not set
# CONFIG_SOUND_TRIX is not set
# CONFIG_SOUND_MSS is not set
# CONFIG_SOUND_UART6850 is not set
# CONFIG_SOUND_AEDSP16 is not set
+#
+# USB support
+#
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=y
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_DSBR is not set
+CONFIG_USB_HID=y
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_WMFORCE is not set
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
#
# Kernel hacking
#
endif
O_OBJS := entry.o traps.o irq.o idle.o time.o process.o signal.o syscalls.o \
- misc.o bitops.o ptrace.o align.o ppc_htab.o semaphore.o
+ misc.o ptrace.o align.o ppc_htab.o semaphore.o bitops.o
ifndef CONFIG_8xx
O_OBJS += hashtable.o
O_OBJS += ppc-stub.o
endif
-ifdef CONFIG_TOTALMP
-O_OBJS += totalmp.o
-endif
-
ifdef CONFIG_PMAC_PBOOK
O_OBJS += sleep.o
endif
ifeq ($(CONFIG_GEMINI),y)
O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o open_pic.o
endif
+ifeq ($(CONFIG_8260),y)
+ O_OBJS += m8260_setup.o ppc8260_pic.o
+endif
all: $(KHEAD) kernel.o
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/system.h>
+#include <asm/cache.h>
struct aligninfo {
unsigned char len;
#define S 0x40 /* single-precision fp, or byte-swap value */
#define HARD 0x80 /* string, stwcx. */
+#define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */
+
/*
* The PowerPC stores certain bits of the instruction that caused the
* alignment exception in the DSISR register. This array maps those
areg = regs->dsisr & 0x1f; /* register to update */
instr = (regs->dsisr >> 10) & 0x7f;
#endif
+
nb = aligninfo[instr].len;
- if (nb == 0)
- return 0; /* too hard or invalid instruction bits */
+ if (nb == 0) {
+ long *p;
+ int i;
+
+ if (instr != DCBZ)
+ return 0; /* too hard or invalid instruction */
+ /*
+ * The dcbz (data cache block zero) instruction
+ * gives an alignment fault if used on non-cacheable
+ * memory. We handle the fault mainly for the
+ * case when we are running with the cache disabled
+ * for debugging.
+ */
+ p = (long *) (regs->dar & -L1_CACHE_BYTES);
+ for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
+ p[i] = 0;
+ return 1;
+ }
+
flags = aligninfo[instr].flags;
/* For the 4xx-family processors, the 'dar' field of the
{0x38,1,OH_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
{0x38,1,OH_BAY_POWER_N}, /* FEATURE_Mediabay_power */
{0x38,0,OH_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,OH_BAY_IDE_ENABLE}, /* FEATURE_Mediabay_IDE_enable */
- {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {0x38,0,OH_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,OH_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
{0x38,0,OH_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
{0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
};
/* Those bits are from a PowerBook. It's possible that desktop machines
{0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
{0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
{0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_Mediabay_IDE_enable */
- {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_Mediabay_IDE_reset */
+ {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
{0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
{0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
{0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
};
-/* Those bits are from an iBook.
+/*
+ * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
+ * Mostly the same as the heathrow.
+ */
+static fbit feature_bits_paddington[] = {
+ {0x38,0,0}, /* FEATURE_null */
+ {0x38,0,0}, /* FEATURE_Serial_reset */
+ {0x38,0,HRW_SCC_ENABLE}, /* FEATURE_Serial_enable */
+ {0x38,0,HRW_SCCA_IO}, /* FEATURE_Serial_IO_A */
+ {0x38,0,HRW_SCCB_IO}, /* FEATURE_Serial_IO_B */
+ {0x38,0,HRW_SWIM_ENABLE}, /* FEATURE_SWIM3_enable */
+ {0x38,0,HRW_MESH_ENABLE}, /* FEATURE_MESH_enable */
+ {0x38,0,HRW_IDE0_ENABLE}, /* FEATURE_IDE0_enable */
+ {0x38,1,HRW_IDE0_RESET_N}, /* FEATURE_IDE0_reset */
+ {0x38,0,HRW_IOBUS_ENABLE}, /* FEATURE_IOBUS_enable */
+ {0x38,1,HRW_BAY_RESET_N}, /* FEATURE_Mediabay_reset */
+ {0x38,1,HRW_BAY_POWER_N}, /* FEATURE_Mediabay_power */
+ {0x38,0,HRW_BAY_PCI_ENABLE}, /* FEATURE_Mediabay_PCI_enable */
+ {0x38,0,HRW_BAY_IDE_ENABLE}, /* FEATURE_IDE1_enable */
+ {0x38,1,HRW_IDE1_RESET_N}, /* FEATURE_IDE1_reset */
+ {0x38,0,HRW_BAY_FLOPPY_ENABLE}, /* FEATURE_Mediabay_floppy_enable */
+ {0x38,0,HRW_BMAC_RESET}, /* FEATURE_BMac_reset */
+ {0x38,0,HRW_BMAC_IO_ENABLE}, /* FEATURE_BMac_IO_enable */
+ {0x38,1,PADD_MODEM_POWER_N}, /* FEATURE_Modem_power */
+ {0x38,0,HRW_SLOW_SCC_PCLK}, /* FEATURE_Slow_SCC_PCLK */
+ {0x38,1,HRW_SOUND_POWER_N}, /* FEATURE_Sound_Power */
+ {0x38,0,HRW_SOUND_CLK_ENABLE}, /* FEATURE_Sound_CLK_Enable */
+ {0x38,0,0}, /* FEATURE_IDE2_enable */
+ {0x38,0,0}, /* FEATURE_IDE2_reset */
+ {0x38,0,0}, /* FEATURE_Mediabay_IDE_switch */
+ {0x38,0,0}, /* FEATURE_Mediabay_content */
+};
+
+/* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
*/
static fbit feature_bits_keylargo[] = {
{0x38,0,0}, /* FEATURE_null */
{0x38,0,0}, /* FEATURE_Serial_IO_B */
{0x38,0,0}, /* FEATURE_SWIM3_enable */
{0x38,0,0}, /* FEATURE_MESH_enable */
- {0x38,0,0}, /* FEATURE_IDE0_enable */
- {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
+ {0x3c,0,0}, /* FEATURE_IDE0_enable */
+ {0x3c,1,0x01000000}, /* FEATURE_IDE0_reset */
{0x38,0,0}, /* FEATURE_IOBUS_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_reset */
- {0x38,0,0}, /* FEATURE_Mediabay_power */
+ {0x34,1,0x00000200}, /* FEATURE_Mediabay_reset */
+ {0x34,1,0x00000400}, /* FEATURE_Mediabay_power */
{0x38,0,0}, /* FEATURE_Mediabay_PCI_enable */
- {0x38,0,0}, /* FEATURE_Mediabay_IDE_enable */
- {0x3c,1,0x08000000}, /* FEATURE_Mediabay_IDE_reset */
+ {0x3c,0,0x0}, /* FEATURE_IDE1_enable */
+ {0x3c,1,0x08000000}, /* FEATURE_IDE1_reset */
{0x38,0,0}, /* FEATURE_Mediabay_floppy_enable */
{0x38,0,0}, /* FEATURE_BMac_reset */
{0x38,0,0}, /* FEATURE_BMac_IO_enable */
{0x38,0,0}, /* FEATURE_Sound_CLK_Enable */
{0x38,0,0}, /* FEATURE_IDE2_enable */
{0x3c,1,0x40000000}, /* FEATURE_IDE2_reset */
+ {0x34,0,0x00001000}, /* FEATURE_Mediabay_IDE_switch */
+ {0x34,0,0x00000100}, /* FEATURE_Mediabay_content */
};
/* definition of a feature controller object */
*/
if (device_is_compatible(np, "Keylargo")) {
feature_add_controller(np, feature_bits_keylargo);
+ } else if (device_is_compatible(np, "paddington")) {
+ feature_add_controller(np, feature_bits_paddington);
} else {
feature_add_controller(np, feature_bits_heathrow);
}
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> setting feature %d in controller @0x%x\n",
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> clearing feature %d in controller @0x%x\n",
if (!controller)
return -ENODEV;
bit = &controller->bits[f];
+ if (!bit->mask)
+ return -EINVAL;
#ifdef DEBUG_FEATURE
printk("feature: <%s> clearing feature %d in controller @0x%x\n",
return PCIBIOS_SUCCESSFUL;
}
-struct gemini_device {
- unsigned short vendor, device;
- unsigned char irq;
- unsigned short cmd;
- unsigned char cache_line, latency;
- void (*init)(struct pci_dev *dev);
-};
-
-static struct gemini_device gemini_map[] = {
- { PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
- { PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
- { PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
-};
-
-static int gemini_map_count = (sizeof( gemini_map ) /
- sizeof( gemini_map[0] ));
-
-
-
-/* This just sets up the known devices on the board. */
-static void __init mapin_device( struct pci_dev *dev )
-{
- struct gemini_device *p;
- unsigned short cmd;
- int i;
-
-
- for( i=0; i < gemini_map_count; i++ ) {
- p = &(gemini_map[i]);
-
- if ( p->vendor == dev->vendor &&
- p->device == dev->device ) {
-
- if (p->irq != 0xff) {
- pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
- dev->irq = p->irq;
- }
-
- if (p->cmd) {
- pci_read_config_word( dev, PCI_COMMAND, &cmd );
- pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
- }
-
- if (p->cache_line)
- pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
-
- if (p->latency)
- pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
- }
- }
-}
-
-#define KB 1024
-#define MB (KB*KB)
-
-#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-
-#define FIRST_IO_ADDR 0x10000
-#define FIRST_MEM_ADDR 0x02000000
-
-#define GEMINI_PCI_MEM_BASE (0xf0000000)
-#define GEMINI_PCI_IO_BASE (0xfe800000)
-
-static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
-static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
-
-static unsigned int io_base = FIRST_IO_ADDR;
-static unsigned int mem_base = FIRST_MEM_ADDR;
-
-
-
-__init void layout_dev( struct pci_dev *dev )
+void __init gemini_pcibios_fixup(void)
{
int i;
- struct pci_bus *bus;
- unsigned short cmd;
- unsigned int reg, base, mask, size, alignto, type;
-
- bus = dev->bus;
-
- /* make any known settings happen */
- mapin_device( dev );
-
- gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
-
- for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
-
- /* MPIC already done */
- if (dev->vendor == PCI_VENDOR_ID_IBM &&
- dev->device == PCI_DEVICE_ID_IBM_MPIC)
- return;
-
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
- gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
- if (!base) {
- dev->resource[i].start = 0;
- continue;
- }
-
- if (base & PCI_BASE_ADDRESS_SPACE_IO) {
- cmd |= PCI_COMMAND_IO;
- base &= PCI_BASE_ADDRESS_IO_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- alignto = MAX(0x400, size);
- base = ALIGN(io_base, alignto);
- io_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg,
- ((pci_io_base + base) & 0x00ffffff) | 0x1);
- dev->resource[i].start = (pci_io_base + base) | 0x1;
- }
-
- else {
- cmd |= PCI_COMMAND_MEMORY;
- type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
- mask = (~base << 1) | 0x1;
- size = (mask & base) & 0xffffffff;
- switch( type ) {
-
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
- PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
- reg += 4;
- continue;
+ struct pci_dev *dev;
+
+ pci_for_each_dev(dev) {
+ for(i = 0; i < 6; i++) {
+ if (dev->resource[i].flags & IORESOURCE_IO) {
+ dev->resource[i].start |= (0xfe << 24);
+ dev->resource[i].end |= (0xfe << 24);
}
-
- alignto = MAX(0x1000, size);
- base = ALIGN(mem_base, alignto);
- mem_base = base + size;
- gemini_pcibios_write_config_dword( bus->number, dev->devfn,
- reg, (pci_mem_base + base));
- dev->resource[i].start = pci_mem_base + base;
}
}
-
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- cmd |= PCI_COMMAND_IO;
-
- gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
- (cmd|PCI_COMMAND_MASTER));
-}
-
-__init void layout_bus( struct pci_bus *bus )
-{
- struct pci_dev *dev;
-
- io_base = ALIGN(io_base, 4*KB);
- mem_base = ALIGN(mem_base, 4*KB);
-
- pci_for_each_dev(dev)
- {
- if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
- ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
- layout_dev( dev );
- }
-}
-
-void __init gemini_pcibios_fixup(void)
-{
- unsigned long orig_mem_base, orig_io_base;
-
- orig_mem_base = pci_mem_base;
- orig_io_base = pci_io_base;
-
- pci_mem_base = orig_mem_base;
- pci_io_base = orig_io_base;
}
decl_config_access_method(gemini);
#include "open_pic.h"
void gemini_setup_pci_ptrs(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
-static unsigned char gemini_switch_map = 0;
static char *gemini_board_families[] = {
- "VGM", "VSS", "KGM", "VGR", "KSS"
-};
-
-static char *gemini_memtypes[] = {
- "EDO DRAM, 60nS", "SDRAM, 15nS, CL=2", "SDRAM, 15nS, CL=2 with ECC"
+ "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
};
+static int gemini_board_count = sizeof(gemini_board_families) /
+ sizeof(gemini_board_families[0]);
static unsigned int cpu_7xx[16] = {
0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
int
gemini_get_cpuinfo(char *buffer)
{
- int i, len;
+ int len;
unsigned char reg, rev;
char *family;
unsigned int type;
reg = readb(GEMINI_FEAT);
family = gemini_board_families[((reg>>4) & 0xf)];
- if (((reg>>4) & 0xf) > 2)
+ if (((reg>>4) & 0xf) > gemini_board_count)
printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
reg = readb(GEMINI_BREV);
len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n",
family, type, (rev + 'A'), (reg & 0xf));
- len += sprintf( buffer+len, "vendor\t\t: %s\n",
- (_get_PVR() & (1<<15)) ? "IBM" : "Motorola");
+ len = sprintf(buffer, "board\t\t: Gemini %s", family);
+ if (type > 9)
+ len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+ else
+ len += sprintf(buffer+len, "%d", type);
- reg = readb(GEMINI_MEMCFG);
- len += sprintf( buffer+len, "memory type\t: %s\n",
- gemini_memtypes[(reg & 0xc0)>>6]);
- len += sprintf( buffer+len, "switches on\t: ");
- for( i=0; i < 8; i++ ) {
- if ( gemini_switch_map & (1<<i))
- len += sprintf(buffer+len, "%d ", i);
- }
- len += sprintf(buffer+len, "\n");
+ len += sprintf(buffer+len, ", rev %c, eco %d\n",
+ (rev + 'A'), (reg & 0xf));
+
+ len += sprintf(buffer+len, "clock\t\t: %dMhz\n",
+ gemini_get_clock_speed());
return len;
}
void __init gemini_openpic_init(void)
{
+
+ OpenPIC = (volatile struct OpenPIC *)
+ grackle_read(0x80005800 + 0x10);
+#if 0
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0,
GEMINI_MPIC_ADDR);
grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
+#endif
OpenPIC_InitSenses = gemini_openpic_initsenses;
OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
void __init gemini_setup_arch(void)
{
- unsigned int cpu;
extern char cmd_line[];
/* nothing but serial consoles... */
sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
- /* The user switches on the front panel can be used as follows:
-
- Switch 0 - adds "debug" to the command line for verbose boot info,
- Switch 7 - boots in single-user mode
-
- */
-
- gemini_switch_map = readb( GEMINI_USWITCH );
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_VERBOSE))
- sprintf(cmd_line, "%s debug", cmd_line);
-
- if ( gemini_switch_map & (1<<GEMINI_SWITCH_SINGLE_USER))
- sprintf(cmd_line, "%s single", cmd_line);
-
printk("Boot arguments: %s\n", cmd_line);
- /* mutter some kind words about who made the CPU */
- cpu = _get_PVR();
- printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
- "Motorola", (cpu & 0xffff));
-
ppc_md.heartbeat = gemini_heartbeat;
ppc_md.heartbeat_reset = HZ/8;
ppc_md.heartbeat_count = 1;
int
gemini_get_clock_speed(void)
{
- unsigned long hid1;
+ unsigned long hid1, pvr = _get_PVR();
int clock;
- unsigned char reg;
-
- hid1 = _get_HID1();
- if ((_get_PVR()>>16) == 8)
+
+ hid1 = (_get_HID1() >> 28) & 0xf;
+ if (PVR_VER(pvr) == 8 ||
+ PVR_VER(pvr) == 12)
hid1 = cpu_7xx[hid1];
else
hid1 = cpu_6xx[hid1];
- reg = readb(GEMINI_BSTAT) & 0xc0;
-
- switch( reg >> 2 ) {
+ switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
case 0:
default:
break;
case 2:
- clock = (hid1*50)/3;
+ clock = (hid1*50);
break;
}
void __init gemini_init_l2(void)
{
- unsigned char reg;
- unsigned long cache;
- int speed;
-
- reg = readb(GEMINI_L2CFG);
-
- /* 750's L2 initializes differently from a 604's. Also note that a Grackle
- bug will hang a dual-604 board, so make sure that doesn't happen by not
- turning on the L2 */
- if ( _get_PVR() >> 16 != 8 ) {
-
- /* check for dual cpus and cry sadly about the loss of an L2... */
- if ((( readb(GEMINI_CPUSTAT) & 0x0c ) >> 2) != 1)
- printk("Sorry. Your dual-604 does not allow the L2 to be enabled due "
- "to a Grackle bug.\n");
- else if ( reg & GEMINI_L2_SIZE_MASK ) {
- printk("Enabling 604 L2 cache: %dKb\n",
- (128<<((reg & GEMINI_L2_SIZE_MASK)>>6)));
- writeb( 1, GEMINI_L2CFG );
- }
- }
+ unsigned char reg, brev, fam, creg;
+ unsigned long cache;
+ unsigned long pvr = _get_PVR();
+
+ reg = readb(GEMINI_L2CFG);
+ brev = readb(GEMINI_BREV);
+ fam = readb(GEMINI_FEAT);
+
+ switch(PVR_VER(pvr)) {
+
+ case 8:
+ if (reg & 0xc0)
+ cache = (((reg >> 6) & 0x3) << 28);
+ else
+ cache = 0x3 << 28;
- /* do a 750 */
- else {
- /* Synergy's first round of 750 boards had the L2 size stuff into the
- board register above. If it's there, it's used; if not, the
- standard default is 1Mb. The L2 type, I'm told, is "most likely
- probably always going to be late-write". --Dan */
-
- if (reg & 0xc0) {
- printk("Enabling 750 L2 cache: %dKb\n",
- (128 << ((reg & 0xc0)>>6)));
- /* take the size given */
- cache = (((reg>>6) & 0x3)<<28);
- }
- else
- {
- printk("Enabling 750 L2 cache: 1M\n");
- /* default of 1Mb */
- cache = 0x3<<28;
- }
-
- reg &= 0x3;
-
- /* a cache ratio of 1:1 and CPU clock speeds in excess of 300Mhz are bad
- things. If found, tune it down to 1:1.5. -- Dan */
- if (!reg) {
-
-printk("3\n");
- speed = gemini_get_clock_speed();
-
- if (speed >= 300) {
- printk("Warning: L2 ratio is 1:1 on a %dMhz processor. Dropping to 1:1.5.\n",
- speed );
- printk("Contact Synergy Microsystems for an ECO to fix this problem\n");
- reg = 0x1;
- }
- }
-
- /* standard stuff */
- cache |= ((1<<reg)<<25);
#ifdef CONFIG_SMP
- /* A couple errata for the 750's (both IBM and Motorola silicon)
- note that you can get missed cache lines on MP implementations.
- The workaround - if you call it that - is to make the L2
- write-through. This is fixed in IBM's 3.1 rev (I'm told), but
- for now, always make 2.x versions use L2 write-through. --Dan */
- if (((_get_PVR()>>8) & 0xf) <= 2)
- {
- cache |= L2CR_L2WT;
- printk("L2 cache: Enabling Write-Through due to 750 Errata.\n");
- }
-#endif
- cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
- _set_L2CR(0);
- _set_L2CR(cache|L2CR_L2I|L2CR_L2E);
+ /* Pre-3.0 processor revs had snooping errata. Leave
+ their L2's disabled with SMP. -- Dan */
+ if (PVR_CFG(pvr) < 3) {
+ printk("Pre-3.0 750; L2 left disabled!\n");
+ return;
+ }
+#endif /* CONFIG_SMP */
+
+ /* Special case: VGM5-B's came before L2 ratios were set on
+ the board. Processor speed shouldn't be too high, so
+ set L2 ratio to 1:1.5. */
+ if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+ reg |= 1;
+
+ /* determine best cache ratio based upon what the board
+ tells us (which sometimes _may_ not be true) and
+ the processor speed. */
+ else {
+ if (gemini_get_clock_speed() > 250)
+ reg = 2;
+ }
+ break;
+ case 12:
+ {
+ static unsigned long l2_size_val = 0;
+
+ if (!l2_size_val)
+ l2_size_val = _get_L2CR();
+ cache = l2_size_val;
+ break;
}
+ case 4:
+ case 9:
+ creg = readb(GEMINI_CPUSTAT);
+ if (((creg & 0xc) >> 2) != 1)
+ printk("Dual-604 boards don't support the use of L2\n");
+ else
+ writeb(1, GEMINI_L2CFG);
+ return;
+ default:
+ printk("Unknown processor; L2 left disabled\n");
+ return;
+ }
+
+ cache |= ((1<<reg) << 25);
+ cache |= (L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE);
+ _set_L2CR(0);
+ _set_L2CR(cache | L2CR_L2I | L2CR_L2E);
+
}
void
void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
+ int i;
int chrp_get_irq( struct pt_regs * );
- void layout_bus( struct pci_bus * );
+
+ for(i = 0; i < GEMINI_LEDS; i++)
+ gemini_led_off(i);
gemini_setup_pci_ptrs();
#ifdef CONFIG_MAGIC_SYSRQ
ppc_md.ppc_kbd_sysrq_xlate = NULL;
#endif
- ppc_md.pcibios_fixup_bus = layout_bus;
+ ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
}
ori r3,r3,start_secondary@l
mtspr SRR0,r3
mtspr SRR1,r4
+ SYNC
rfi
#endif /* CONFIG_SMP */
tlbsync /* ... on all CPUs */
sync
#endif
-
+
bl load_up_mmu
/* Set up for using our exception vectors */
mtspr IBAT1U,r3
blr
#endif
+
+#ifdef CONFIG_8260
+/* Jump into the system reset for the rom.
+ * We first disable the MMU, and then jump to the ROM reset address.
+ *
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
+ */
+ .globl m8260_gorom
+m8260_gorom:
+ li r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ lis r6,2f@h
+ addis r6,r6,-KERNELBASE@h
+ ori r6,r6,2f@l
+ mtspr SRR0,r6
+ mtspr SRR1,r5
+ rfi
+2:
+ mtlr r4
+ blr
+#endif
/*
* We put a few things here that have to be page-aligned.
mtspr DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr IC_CST, r8
-#if 0
+#ifdef CONFIG_8xx_COPYBACK
mtspr DC_CST, r8
#else
/* For a debug option, I left this here to easily enable
* only perform the attribute functions.
*/
InstructionTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, SRR0 /* Get effective address of fault */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3780
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_EPN, r20 /* Have to use MD_EPN for walk, MI_EPN can't */
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load the MI_TWC with the attributes
*/
tophys(r21,r21)
ori r21,r21,1 /* Set valid bit */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_TWC, r21 /* Set page attributes */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
+#if 0
+ ori r20, r20, _PAGE_ACCESSED
+ stw r20, 0(r21)
+#endif
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MI_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x2d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MI_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b InstructionAccess
. = 0x1200
DataStoreTLBMiss:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
stw r21, 4(r0)
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, don't try to find a pte */
/* We have a pte table, so load fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
- mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ mfspr r20, MD_TWC /* ....and get the pte address */
+ lwz r20, 0(r20) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r21, r20, 0, 27, 27
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
+ mtspr MD_TWC, r21
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+#if 0
+ ori r20, r20, 0x00f0
+#else
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#endif
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2: mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
/* This is an instruction TLB error on the MPC8xx. This could be due
*/
. = 0x1400
DataTLBError:
+#ifdef CONFIG_8xx_CPU6
+ stw r3, 8(r0)
+ li r3, 0x3f80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr M_TW, r20 /* Save a couple of working registers */
mfcr r20
stw r20, 0(r0)
mfspr r20, M_TWB /* Get level 1 table entry address */
lwz r21, 0(r20) /* Get the level 1 entry */
- rlwinm. r20, r21,0,0,20 /* Extract page descriptor page address */
+ rlwinm. r20, r21,0,0,19 /* Extract page descriptor page address */
beq 2f /* If zero, bail */
/* We have a pte table, so fetch the pte from the table.
*/
tophys(r21, r21)
ori r21, r21, 1 /* Set valid bit in physical L2 page */
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3b80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_TWC, r21 /* Load pte table base address */
mfspr r21, MD_TWC /* ....and get the pte address */
- lwz r21, 0(r21) /* Get the pte */
+ lwz r20, 0(r21) /* Get the pte */
- andi. r20, r21, _PAGE_RW /* Is it writeable? */
+ andi. r21, r20, _PAGE_RW /* Is it writeable? */
beq 2f /* Bail out if not */
- ori r21, r21, _PAGE_DIRTY /* Update changed bit */
- mfspr r20, MD_TWC /* Get pte address again */
- stw r21, 0(r20) /* and update pte in table */
+ /* Update 'changed', among others.
+ */
+ ori r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+ mfspr r21, MD_TWC /* Get pte address again */
+ stw r20, 0(r21) /* and update pte in table */
/* Set four subpage valid bits (24, 25, 26, and 27).
- * Since we currently run MD_CTR.PPCS = 0, the manual says,
- * "If the page size is larger than 4k byte, then all the
- * 4 bits should have the same value."
- * I don't really know what to do if the page size is 4k Bytes,
- * but I know setting them all to 0 does not work, and setting them
- * all to 1 does, so that is the way it is right now.
- * BTW, these four bits map to the software only bits in the
- * linux page table. I used to turn them all of, but now just
- * set them all for the hardware.
- li r20, 0x00f0
- andc r20, r21, r20
- ori r20, r20, 0x0080
+ * Clear bit 28 (which should be in the PTE, but we do this anyway).
*/
- ori r20, r21, 0x00f0
-
+ li r21, 0x00f0
+ rlwimi r20, r21, 0, 24, 28
+#ifdef CONFIG_8xx_CPU6
+ li r3, 0x3d80
+ stw r3, 12(r0)
+ lwz r3, 12(r0)
+#endif
mtspr MD_RPN, r20 /* Update TLB entry */
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
rfi
2:
mfspr r20, M_TW /* Restore registers */
lwz r21, 0(r0)
mtcr r21
lwz r21, 4(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
b DataAccess
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
STD_EXCEPTION(0x1900, Trap_19, UnknownException)
STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+
/* On the MPC8xx, these next four traps are used for development
* support of breakpoints and such. Someday I will get around to
* using them.
kfree(ptr);
}
-#ifdef CONFIG_8xx
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 82xx. Just bear with me,
+ * the internal interrupt controller on 8xx and 8260. Just bear with me,
* I don't like this either and I am searching a better solution. For
* now, this is what I need. -- Dan
*/
#else
void free_irq(unsigned int irq, void *dev_id)
{
-#ifndef CONFIG_8xx
- request_irq(irq, NULL, 0, NULL, dev_id);
-#else
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
request_8xxirq(irq, NULL, 0, NULL, dev_id);
+#else
+ request_irq(irq, NULL, 0, NULL, dev_id);
#endif
}
#endif
--- /dev/null
+/*
+ * $Id: m8xx_setup.c,v 1.4 1999/09/18 18:40:36 dmalek Exp $
+ *
+ * linux/arch/ppc/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ * Further modified for generic 8xx and 8260 by Dan.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/blk.h>
+#include <linux/ioport.h>
+#include <linux/ide.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#include <asm/machdep.h>
+
+#include "time.h"
+#include "ppc8260_pic.h"
+
+static int m8260_set_rtc_time(unsigned long time);
+unsigned long m8260_get_rtc_time(void);
+void m8260_calibrate_decr(void);
+
+#if 0
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+#endif
+
+extern unsigned long loops_per_sec;
+
+unsigned char __res[sizeof(bd_t)];
+unsigned long empty_zero_page[1024];
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start; /* starting block # of image */
+#endif
+
+extern char saved_command_line[256];
+
+extern unsigned long find_available_memory(void);
+extern void m8260_cpm_reset(void);
+
+void __init adbdev_init(void)
+{
+}
+
+void __init
+m8260_setup_arch(void)
+{
+ extern char cmd_line[];
+
+ printk("Boot arguments: %s\n", cmd_line);
+
+ /* Reset the Communication Processor Module.
+ */
+ m8260_cpm_reset();
+}
+
+void
+abort(void)
+{
+#ifdef CONFIG_XMON
+ extern void xmon(void *);
+ xmon(0);
+#endif
+ machine_restart(NULL);
+}
+
+/* The decrementer counts at the system (internal) clock frequency
+ * divided by four.
+ */
+void __init m8260_calibrate_decr(void)
+{
+ bd_t *binfo = (bd_t *)__res;
+ int freq, divisor;
+
+ freq = (binfo->bi_intfreq * 1000000);
+ divisor = 16;
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/* The 8260 has an internal 1-second timer update register that
+ * we should use for this purpose.
+ */
+static uint rtc_time;
+static int
+m8260_set_rtc_time(unsigned long time)
+{
+ rtc_time = time;
+ return(0);
+}
+
+unsigned long __init
+m8260_get_rtc_time(void)
+{
+
+ /* Get time from the RTC.
+ */
+ return((unsigned long)rtc_time);
+}
+
+void
+m8260_restart(char *cmd)
+{
+ extern void m8260_gorom(bd_t *bi, uint addr);
+
+ m8260_gorom(NULL, 0xff000100);
+}
+
+void
+m8260_power_off(void)
+{
+ m8260_restart(NULL);
+}
+
+void
+m8260_halt(void)
+{
+ m8260_restart(NULL);
+}
+
+
+int m8260_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp;
+
+ bp = (bd_t *)__res;
+
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq /*/ 1000000*/,
+ bp->bi_busfreq /*/ 1000000*/);
+
+ return len;
+}
+
+/* Initialize the internal interrupt controller. The number of
+ * interrupts supported can vary with the processor type, and the
+ * 8260 family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+void __init
+m8260_init_IRQ(void)
+{
+ int i;
+ void cpm_interrupt_init(void);
+
+#if 0
+ ppc8260_pic.irq_offset = 0;
+#endif
+ for ( i = 0 ; i < NR_SIU_INTS ; i++ )
+ irq_desc[i].handler = &ppc8260_pic;
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ immr->im_intctl.ic_sicr = 0;
+ immr->im_intctl.ic_siprr = 0x05309770;
+ immr->im_intctl.ic_scprrh = 0x05309770;
+ immr->im_intctl.ic_scprrl = 0x05309770;
+
+}
+
+
+void __init
+m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+
+ if ( r3 )
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+ /* take care of cmd line */
+ if ( r6 )
+ {
+
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = m8260_setup_arch;
+ ppc_md.setup_residual = m8260_setup_residual;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = m8260_init_IRQ;
+ ppc_md.get_irq = m8260_get_irq;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = m8260_restart;
+ ppc_md.power_off = m8260_power_off;
+ ppc_md.halt = m8260_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = m8260_set_rtc_time;
+ ppc_md.get_rtc_time = m8260_get_rtc_time;
+ ppc_md.calibrate_decr = m8260_calibrate_decr;
+
+#if 0
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_pretranslate = pckbd_pretranslate;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#else
+ ppc_md.kbd_setkeycode = NULL;
+ ppc_md.kbd_getkeycode = NULL;
+ ppc_md.kbd_translate = NULL;
+ ppc_md.kbd_unexpected_up = NULL;
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = NULL;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = m8xx_ide_insw;
+ ppc_ide_md.outsw = m8xx_ide_outsw;
+ ppc_ide_md.default_irq = m8xx_ide_default_irq;
+ ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
+ ppc_ide_md.check_region = m8xx_ide_check_region;
+ ppc_ide_md.request_region = m8xx_ide_request_region;
+ ppc_ide_md.release_region = m8xx_ide_release_region;
+ ppc_ide_md.fix_driveid = m8xx_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
+ ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
+}
+
+void
+prom_init(uint r3, uint r4, uint r5, uint r6)
+{
+ /* Nothing to do now, but we are called immediatedly upon
+ * kernel start up with MMU disabled, so if there is
+ * anything we need to do......
+ */
+}
+
+/* Mainly for ksyms.
+*/
+int
+request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flag, const char *naem, void *dev)
+{
+ panic("request IRQ\n");
+}
abort(void)
{
#ifdef CONFIG_XMON
- extern void xmon(void *);
xmon(0);
#endif
machine_restart(NULL);
#include <asm/errno.h>
#include <asm/processor.h>
#include <asm/page.h>
+#include <asm/cache.h>
#include "ppc_asm.h"
#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
* This is a no-op on the 601.
*/
_GLOBAL(flush_instruction_cache)
+#ifdef CONFIG_8xx
+ isync
+ lis r5, IDC_INVALL@h
+ mtspr IC_CST, r5
+#else
mfspr r3,PVR
rlwinm r3,r3,16,16,31
cmpi 0,r3,1
mfspr r3,HID0
ori r3,r3,HID0_ICFI
mtspr HID0,r3
+#endif /* CONFIG_8xx */
SYNC
blr
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
beqlr /* for 601, do nothing */
- li r4,0x0FFF
- andc r3,r3,r4 /* Get page base address */
+ rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
mr r6,r3
* void atomic_clear_mask(atomic_t mask, atomic_t *addr)
* void atomic_set_mask(atomic_t mask, atomic_t *addr);
*/
+#if 0 /* now inline - paulus */
_GLOBAL(atomic_add)
10: lwarx r5,0,r4 /* Fetch old value & reserve */
add r5,r5,r3 /* Perform 'add' operation */
subi r5,r5,1 /* Perform 'add' operation */
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
- cmpi 0,r5,0 /* Return 'true' IFF 0 */
- li r3,1
- beqlr
- li r3,0
+ cntlzw r3,r5
+ srwi r3,r3,5
blr
+#endif /* 0 */
_GLOBAL(atomic_clear_mask)
10: lwarx r5,0,r4
andc r5,r5,r3
#include <linux/nvram.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/nvram.h>
#include <linux/adb.h>
#include <linux/pmu.h>
+#undef DEBUG
+
/*
* Read and write the non-volatile RAM on PowerMacs and CHRP machines.
*/
static volatile unsigned char *nvram_data;
static int nvram_mult, is_core_99;
static char* nvram_image;
+static int core99_bank = 0;
+
+extern int pmac_newworld;
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
+#define CORE99_SIGNATURE 0x5a
+#define CORE99_ADLER_START 0x14
+
+/* Core99 nvram is a flash */
+#define CORE99_FLASH_STATUS_DONE 0x80
+#define CORE99_FLASH_STATUS_ERR 0x38
+#define CORE99_FLASH_CMD_ERASE_CONFIRM 0xd0
+#define CORE99_FLASH_CMD_ERASE_SETUP 0x20
+#define CORE99_FLASH_CMD_RESET 0xff
+#define CORE99_FLASH_CMD_WRITE_SETUP 0x40
+
+/* CHRP NVRAM header */
+struct chrp_header {
+ u8 signature;
+ u8 cksum;
+ u16 len;
+ char name[12];
+ u8 data[0];
+};
+
+struct core99_header {
+ struct chrp_header hdr;
+ u32 adler;
+ u32 generation;
+ u32 reserved[2];
+};
+
+static int nvram_partitions[3];
+
+static u8
+chrp_checksum(struct chrp_header* hdr)
+{
+ u8 *ptr;
+ u16 sum = hdr->signature;
+ for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+ sum += *ptr;
+ while (sum > 0xFF)
+ sum = (sum & 0xFF) + (sum>>8);
+ return sum;
+}
+
+static u32
+core99_calc_adler(u8 *buffer)
+{
+ int cnt;
+ u32 low, high;
+
+ buffer += CORE99_ADLER_START;
+ low = 1;
+ high = 0;
+ for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+ if ((cnt % 5000) == 0) {
+ high %= 65521UL;
+ high %= 65521UL;
+ }
+ low += buffer[cnt];
+ high += low;
+ }
+ low %= 65521UL;
+ high %= 65521UL;
+
+ return (high << 16) | low;
+}
+
+static u32
+core99_check(u8* datas)
+{
+ struct core99_header* hdr99 = (struct core99_header*)datas;
+
+ if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+#ifdef DEBUG
+ printk("Invalid signature\n");
+#endif
+ return 0;
+ }
+ if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+#ifdef DEBUG
+ printk("Invalid checksum\n");
+#endif
+ return 0;
+ }
+ if (hdr99->adler != core99_calc_adler(datas)) {
+#ifdef DEBUG
+ printk("Invalid adler\n");
+#endif
+ return 0;
+ }
+ return hdr99->generation;
+}
+
+static int
+core99_erase_bank(int bank)
+{
+ int stat, i;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
+ out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
+ do { stat = in_8(base); }
+ while(!(stat & CORE99_FLASH_STATUS_DONE));
+ out_8(base, CORE99_FLASH_CMD_RESET);
+ if (stat & CORE99_FLASH_STATUS_ERR) {
+ printk("nvram: flash error 0x%02x on erase !\n", stat);
+ return -ENXIO;
+ }
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != 0xff) {
+ printk("nvram: flash erase failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static int
+core99_write_bank(int bank, u8* datas)
+{
+ int i, stat = 0;
+
+ u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+
+ for (i=0; i<NVRAM_SIZE; i++) {
+ out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
+ out_8(base+i, datas[i]);
+ do { stat = in_8(base); }
+ while(!(stat & CORE99_FLASH_STATUS_DONE));
+ if (stat & CORE99_FLASH_STATUS_ERR)
+ break;
+ }
+ out_8(base, CORE99_FLASH_CMD_RESET);
+ if (stat & CORE99_FLASH_STATUS_ERR) {
+ printk("nvram: flash error 0x%02x on write !\n", stat);
+ return -ENXIO;
+ }
+ for (i=0; i<NVRAM_SIZE; i++)
+ if (base[i] != datas[i]) {
+ printk("nvram: flash write failed !\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+static void
+lookup_partitions(void)
+{
+ u8 buffer[17];
+ int i, offset;
+ struct chrp_header* hdr;
+
+ if (pmac_newworld) {
+ nvram_partitions[pmac_nvram_OF] = -1;
+ nvram_partitions[pmac_nvram_XPRAM] = -1;
+ nvram_partitions[pmac_nvram_NR] = -1;
+ hdr = (struct chrp_header *)buffer;
+
+ offset = 0;
+ do {
+ for (i=0;i<16;i++)
+ buffer[i] = nvram_read_byte(offset+i);
+ if (!strcmp(hdr->name, "common"))
+ nvram_partitions[pmac_nvram_OF] = offset + 0x10;
+ if (!strcmp(hdr->name, "APL,MacOS75")) {
+ nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
+ nvram_partitions[pmac_nvram_NR] = offset + 0x110;
+ }
+ offset += (hdr->len * 0x10);
+ } while(offset < NVRAM_SIZE);
+ } else {
+ nvram_partitions[pmac_nvram_OF] = 0x1800;
+ nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
+ nvram_partitions[pmac_nvram_NR] = 0x1400;
+ }
+#ifdef DEBUG
+ printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
+ printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
+ printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+#endif
+}
+
__init
void pmac_nvram_init(void)
{
}
nvram_naddrs = dp->n_addrs;
is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99)
- {
+ if (is_core_99) {
int i;
- if (nvram_naddrs < 1)
+ u32 gen_bank0, gen_bank1;
+
+ if (nvram_naddrs < 1) {
+ printk(KERN_ERR "nvram: no address\n");
return;
- nvram_image = kmalloc(dp->addrs[0].size, GFP_KERNEL);
- if (!nvram_image)
+ }
+ nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
+ if (!nvram_image) {
+ printk(KERN_ERR "nvram: can't allocate image\n");
return;
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- for (i=0; i<dp->addrs[0].size; i++)
- nvram_image[i] = in_8(nvram_data + i);
+ }
+ nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+#ifdef DEBUG
+ printk("nvram: Checking bank 0...\n");
+#endif
+ gen_bank0 = core99_check((u8 *)nvram_data);
+ gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+ core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+#ifdef DEBUG
+ printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+ printk("nvram: Active bank is: %d\n", core99_bank);
+#endif
+ for (i=0; i<NVRAM_SIZE; i++)
+ nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
nvram_mult = 1;
}
}
+void
+pmac_nvram_update(void)
+{
+ struct core99_header* hdr99;
+
+ if (!is_core_99 || !nvram_data || !nvram_image)
+ return;
+ if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+ NVRAM_SIZE))
+ return;
+#ifdef DEBUG
+ printk("Updating nvram...\n");
+#endif
+ hdr99 = (struct core99_header*)nvram_image;
+ hdr99->generation++;
+ hdr99->hdr.signature = CORE99_SIGNATURE;
+ hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+ hdr99->adler = core99_calc_adler(nvram_image);
+ core99_bank = core99_bank ? 0 : 1;
+ if (core99_erase_bank(core99_bank)) {
+ printk("nvram: Error erasing bank %d\n", core99_bank);
+ return;
+ }
+ if (core99_write_bank(core99_bank, nvram_image))
+ printk("nvram: Error writing bank %d\n", core99_bank);
+}
+
__openfirmware
unsigned char nvram_read_byte(int addr)
{
}
eieio();
}
+
+int
+pmac_get_partition(int partition)
+{
+ return nvram_partitions[partition];
+}
+
+u8
+pmac_xpram_read(int xpaddr)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return 0;
+
+ return nvram_read_byte(xpaddr + offset);
+}
+
+void
+pmac_xpram_write(int xpaddr, u8 data)
+{
+ int offset = nvram_partitions[pmac_nvram_XPRAM];
+
+ if (offset < 0)
+ return;
+
+ nvram_write_byte(xpaddr + offset, data);
+}
+
+
bp->io_base);
}
-#define GRACKLE_STG_ENABLE 0x00000040
+#define GRACKLE_PICR1_STG 0x00000040
+#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
/* N.B. this is called before bridges is initialized, so we can't
use grackle_pcibios_{read,write}_config_dword. */
out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
val = in_le32((volatile unsigned int *)bp->cfg_data);
- val = enable? (val | GRACKLE_STG_ENABLE): (val & ~GRACKLE_STG_ENABLE);
+ val = enable? (val | GRACKLE_PICR1_STG) :
+ (val & ~GRACKLE_PICR1_STG);
out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
out_le32((volatile unsigned int *)bp->cfg_data, val);
}
+static inline void grackle_set_loop_snoop(struct bridge_data *bp, int enable)
+{
+ unsigned int val;
+
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ val = in_le32((volatile unsigned int *)bp->cfg_data);
+ val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
+ (val & ~GRACKLE_PICR1_LOOPSNOOP);
+ out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+ out_le32((volatile unsigned int *)bp->cfg_data, val);
+}
+
+
void __init pmac_find_bridges(void)
{
int bus;
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
-#if 0 /* Disabled for now, HW problems */
+ if (machine_is_compatible("AAPL,PowerBook1998"))
+ grackle_set_loop_snoop(bp, 1);
+#if 0 /* Disabled for now, HW problems ??? */
grackle_set_stg(bp, 1);
#endif
} else {
{
int irq, bits;
- for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| ppc_lost_interrupts[i];
if (bits == 0)
continue;
- irq -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
/* The previous version of this code allowed for this case, we
}
else
{
- for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| ppc_lost_interrupts[i];
if (bits == 0)
continue;
- irq -= cntlzw(bits);
+ irq += __ilog2(bits);
break;
}
}
if (max_real_irqs > 32)
out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
(void)in_le32(&pmac_irq_hw[0]->flag);
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while(in_le32(&pmac_irq_hw[0]->enable) != ppc_cached_irq_mask[0]);
+ /* make sure mask gets to controller before we return to caller */
+ mb();
+ (void)in_le32(&pmac_irq_hw[0]->enable);
}
void
extern char saved_command_line[];
+extern int pmac_newworld;
+
#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
extern void zs_kgdb_hook(int tty_num);
}
}
+ /* Indicate newworld/oldworld */
+ len += sprintf(buffer+len, "pmac-generation\t: %s\n",
+ pmac_newworld ? "NewWorld" : "OldWorld");
+
+
return len;
}
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
struct adb_request req;
#endif /* CONFIG_ADB_CUDA */
+ pmac_nvram_update();
+
switch (sys_ctrler) {
#ifdef CONFIG_ADB_CUDA
case SYS_CTRLER_CUDA:
static int initialized = 0;
static int kgdb_active = 0;
+static int kgdb_started = 0;
static u_int fault_jmp_buf[100];
static int kdebug;
flush_instruction_cache();
}
-static inline int get_msr()
+static inline int get_msr(void)
{
int msr;
asm volatile("mfmsr %0" : "=r" (msr):);
return SIGHUP; /* default for things we don't know about */
}
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
/*
* This function does all command processing for interfacing to gdb.
*/
return;
}
kgdb_active = 1;
+ kgdb_started = 1;
#ifdef KGDB_DEBUG
printk("kgdb: entering handle_exception; trap [0x%x]\n",
sigval = computeSignal(regs->trap);
ptr = remcomOutBuffer;
+#if 0
*ptr++ = 'S';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
+#else
+ *ptr++ = 'T';
+ *ptr++ = hexchars[sigval >> 4];
+ *ptr++ = hexchars[sigval & 0xf];
+ *ptr++ = hexchars[PC_REGNUM >> 4];
+ *ptr++ = hexchars[PC_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex((char *)®s->nip, ptr, 4);
+ *ptr++ = ';';
+ *ptr++ = hexchars[SP_REGNUM >> 4];
+ *ptr++ = hexchars[SP_REGNUM & 0xf];
+ *ptr++ = ':';
+ ptr = mem2hex(((char *)®s) + SP_REGNUM*4, ptr, 4);
+ *ptr++ = ';';
+#endif
*ptr++ = 0;
} else {
strcpy(remcomOutBuffer, "E03");
}
+ flush_icache_range(addr, addr+length);
} else {
strcpy(remcomOutBuffer, "E02");
}
case 's':
kgdb_flush_cache_all();
regs->msr |= MSR_SE;
+#if 0
set_msr(msr | MSR_SE);
+#endif
unlock_kernel();
kgdb_active = 0;
return;
}
asm(" .globl breakinst
- breakinst: trap
+ breakinst: .long 0x7d821008
");
}
+
+/* Output string in GDB O-packet format if GDB has connected. If nothing
+ output, returns 0 (caller must then handle output). */
+int
+kgdb_output_string (const char* s, unsigned int count)
+{
+ char buffer[512];
+
+ if (!kgdb_started)
+ return 0;
+
+ count = (count <= (sizeof(buffer) / 2 - 2))
+ ? count : (sizeof(buffer) / 2 - 2);
+
+ buffer[0] = 'O';
+ mem2hex (s, &buffer[1], count);
+ putpacket(buffer);
+
+ return 1;
+ }
+
+#ifndef CONFIG_8xx
+
+/* I don't know why other platforms don't need this. The function for
+ * the 8xx is found in arch/ppc/8xx_io/uart.c. -- Dan
+ */
+void
+kgdb_map_scc(void)
+{
+}
+#endif
--- /dev/null
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/irq.h>
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#include "ppc8260_pic.h"
+
+/* The 8260 internal interrupt controller. It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static u_char irq_to_siureg[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_char irq_to_siubit[] = {
+ 31, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 29, 30, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static void m8260_mask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_unmask_irq(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_mask_and_ack(unsigned int irq_nr)
+{
+ int bit, word;
+ volatile uint *simr, *sipnr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ sipnr = &(immr->im_intctl.ic_sipnrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+ sipnr[word] = 1 << bit;
+}
+
+struct hw_interrupt_type ppc8260_pic = {
+ " 8260 SIU ",
+ NULL,
+ NULL,
+ m8260_unmask_irq,
+ m8260_mask_irq,
+ m8260_mask_and_ack,
+ 0
+};
+
+
+int
+m8260_get_irq(struct pt_regs *regs)
+{
+ int irq;
+ unsigned long bits;
+
+ /* For MPC8260, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = immr->im_intctl.ic_sivec;
+ irq = bits >> 26;
+#if 0
+ irq += ppc8260_pic.irq_offset;
+#endif
+ return irq;
+}
+
--- /dev/null
+
+#ifndef _PPC_KERNEL_PPC8260_H
+#define _PPC_KERNEL_PPC8260_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type ppc8260_pic;
+
+void m8260_pic_init(void);
+void m8260_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake);
+int m8260_get_irq(struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_PPC8260_H */
#include <asm/mpc8xx.h>
#include "ppc8xx_pic.h"
-/* The 8xx or 82xx internal interrupt controller. It is usually
+/* The 8xx internal interrupt controller. It is usually
* the only interrupt controller. Some boards, like the MBX and
* Sandpoint have the 8259 as a secondary controller. Depending
* upon the processor type, the internal controller can have as
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_unmask_irq(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] |= (1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
-#endif
}
static void m8xx_mask_and_ack(unsigned int irq_nr)
word = irq_nr >> 5;
ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
-#ifdef CONFIG_82xx
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask[word] =
- ppc_cached_irq_mask[word];
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend[word] = 1 << (31-bit);
-#else
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
ppc_cached_irq_mask[word];
((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-bit);
-#endif
}
struct hw_interrupt_type ppc8xx_pic = {
/* The MBX is the only 8xx board that uses the 8259.
*/
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
{
int bits, irq;
unsigned long irqflags, const char * devname, void *dev_id)
{
-#ifdef CONFIG_MBX
+#if defined(CONFIG_MBX) && defined(CONFIG_PCI)
irq += i8259_pic.irq_offset;
return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
#else
#define TMPBUFLEN 256
char buf[TMPBUFLEN], *p;
static const char *sizestrings[4] = {
- "unknown size", "256KB", "512KB", "1MB"
+ "2MB", "256KB", "512KB", "1MB"
};
static const char *clockstrings[8] = {
"clock disabled", "+1 clock", "+1.5 clock", "reserved(3)",
extern void do_lost_interrupts(unsigned long);
extern int do_signal(sigset_t *, struct pt_regs *);
-asmlinkage long long __ashrdi3(long long, int);
-asmlinkage long long __lshrdi3(long long, int);
-asmlinkage int abs(int);
+long long __ashrdi3(long long, int);
+long long __ashldi3(long long, int);
+long long __lshrdi3(long long, int);
+int abs(int);
EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(do_signal);
#endif
#endif
-EXPORT_SYMBOL(atomic_add);
-EXPORT_SYMBOL(atomic_sub);
-EXPORT_SYMBOL(atomic_inc);
-EXPORT_SYMBOL(atomic_inc_return);
-EXPORT_SYMBOL(atomic_dec);
-EXPORT_SYMBOL(atomic_dec_return);
-EXPORT_SYMBOL(atomic_dec_and_test);
-
EXPORT_SYMBOL(set_bit);
EXPORT_SYMBOL(clear_bit);
EXPORT_SYMBOL(change_bit);
EXPORT_SYMBOL(test_and_set_bit);
EXPORT_SYMBOL(test_and_clear_bit);
EXPORT_SYMBOL(test_and_change_bit);
-#if 0
-EXPORT_SYMBOL(ffz);
-EXPORT_SYMBOL(find_first_zero_bit);
-EXPORT_SYMBOL(find_next_zero_bit);
-#endif
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
#endif /* CONFIG_NVRAM */
EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL(xmon);
#endif
EXPORT_SYMBOL(down_read_failed);
+
+extern void (*debugger)(struct pt_regs *regs);
+extern int (*debugger_bpt)(struct pt_regs *regs);
+extern int (*debugger_sstep)(struct pt_regs *regs);
+extern int (*debugger_iabr_match)(struct pt_regs *regs);
+extern int (*debugger_dabr_match)(struct pt_regs *regs);
+extern void (*debugger_fault_handler)(struct pt_regs *regs);
+
+EXPORT_SYMBOL(debugger);
+EXPORT_SYMBOL(debugger_bpt);
+EXPORT_SYMBOL(debugger_sstep);
+EXPORT_SYMBOL(debugger_iabr_match);
+EXPORT_SYMBOL(debugger_dabr_match);
+EXPORT_SYMBOL(debugger_fault_handler);
{
int error;
char * filename;
- lock_kernel();
+
filename = getname((char *) a0);
error = PTR_ERR(filename);
if (IS_ERR(filename))
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
- unlock_kernel();
-
return error;
}
unsigned int rtas_size = 0;
unsigned int old_rtas = 0;
+/* Set for a newworld machine */
int use_of_interrupt_tree = 0;
+int pmac_newworld = 0;
+
static struct device_node *allnodes = 0;
#ifdef CONFIG_BOOTX_TEXT
static void
setup_disp_fake_bi(ihandle dp)
{
- unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
unsigned address;
boot_infos_t* bi;
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
- char* model;
-
- /* Here, we decide if we'll use the interrupt-tree (new Core99 code) or not.
- * This code was only tested with Core99 machines so far, but should be easily
- * adapted to older newworld machines (iMac, B&W G3, Lombard).
- */
- model = get_property(allnodes, "model", 0);
- if ((boot_infos == 0) && model && (strcmp(model, "PowerBook2,1") == 0
- || strcmp(model, "PowerMac2,1") == 0 || strcmp(model, "PowerMac3,1") == 0))
+
+ /* All newworld machines now use the interrupt tree */
+ struct device_node *np = allnodes;
+ while(np) {
+ if (get_property(np, "interrupt-parent", 0)) {
+ pmac_newworld = 1;
+ break;
+ }
+ np = np->allnext;
+ }
+ if (boot_infos == 0 && pmac_newworld)
use_of_interrupt_tree = 1;
mem = finish_node(allnodes, mem, NULL);
#ifdef CONFIG_XMON
xmon(NULL);
#endif
- prom_exit();
+ for (;;)
+ prom_exit();
}
#ifdef CONFIG_BOOTX_TEXT
" .align 2\n" \
" .long 1b,3b\n" \
".text" \
- : "=r"(x) : "r"(addr))
+ : "=r"(x) : "r"(addr) : " %0")
#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500))
#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504))
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#include <asm/immap_8260.h>
+#endif
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/feature.h>
* on pmac as well so we don't need the ifdef's.
* Until we get multiple-console support in here
* that is. -- Cort
+ * Maybe tie it to serial consoles, since this is really what
+ * these processors use on existing boards. -- Dan
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
struct screen_info screen_info = {
0, 25, /* orig-x, orig-y */
0, /* unused */
}
break;
case 0x0050:
- len += sprintf(len+buffer, "821\n");
+ len += sprintf(len+buffer, "8xx\n");
break;
case 0x0081:
- len += sprintf(len+buffer, "8240\n");
+ len += sprintf(len+buffer, "82xx\n");
break;
case 0x4011:
len += sprintf(len+buffer, "405GP\n");
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
if ( have_of )
{
struct device_node *cpu_node;
unsigned long r6, unsigned long r7)
{
parse_bootinfo();
-
+
if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
#ifndef CONFIG_MACH_SPECIFIC
/* if we didn't get any bootinfo telling us what we are... */
if ( _machine == 0 )
oak_init(r3, r4, r5, r6, r7);
#elif defined(CONFIG_8xx)
m8xx_init(r3, r4, r5, r6, r7);
+#elif defined(CONFIG_8260)
+ m8260_init(r3, r4, r5, r6, r7);
#else
#error "No board type has been defined for identify_machine()!"
#endif /* CONFIG_4xx */
map_bootx_text();
#endif
+#ifdef CONFIG_ALL_PPC
+ feature_init();
+#endif
+
#ifdef CONFIG_XMON
xmon_map_scc();
if (strstr(cmd_line, "xmon"))
xmon(0);
#endif /* CONFIG_XMON */
if ( ppc_md.progress ) ppc_md.progress("setup_arch: enter", 0x3eab);
+
#if defined(CONFIG_KGDB)
+ kgdb_map_scc();
set_debug_traps();
breakpoint();
#endif
ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
+
paging_init();
}
int i;
unsigned short *stringcast;
-
id->config = __le16_to_cpu(id->config);
id->cyls = __le16_to_cpu(id->cyls);
id->reserved2 = __le16_to_cpu(id->reserved2);
id->vendor1 = __le16_to_cpu(id->vendor1);
id->vendor2 = __le16_to_cpu(id->vendor2);
stringcast = (unsigned short *)&id->serial_no[0];
- for (i=0; i<(20/2); i++)
+ for (i = 0; i < (20/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->buf_type = __le16_to_cpu(id->buf_type);
id->buf_size = __le16_to_cpu(id->buf_size);
id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
stringcast = (unsigned short *)&id->fw_rev[0];
- for (i=0; i<(8/2); i++)
+ for (i = 0; i < (8/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
stringcast = (unsigned short *)&id->model[0];
- for (i=0; i<(40/2); i++)
+ for (i = 0; i < (40/2); i++)
stringcast[i] = __le16_to_cpu(stringcast[i]);
id->dword_io = __le16_to_cpu(id->dword_io);
id->reserved50 = __le16_to_cpu(id->reserved50);
id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
id->eide_pio = __le16_to_cpu(id->eide_pio);
id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- for (i=0; i<2; i++)
+ for (i = 0; i < 2; i++)
id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
id->queue_depth = __le16_to_cpu(id->queue_depth);
- for (i=0; i<4; i++)
+ for (i = 0; i < 4; i++)
id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
id->major_rev_num = __le16_to_cpu(id->major_rev_num);
id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
id->word92 = __le16_to_cpu(id->word92);
id->hw_config = __le16_to_cpu(id->hw_config);
- for (i=0; i<32; i++)
+ for (i = 0; i < 32; i++)
id->words94_125[i] = __le16_to_cpu(id->words94_125[i]);
id->last_lun = __le16_to_cpu(id->last_lun);
id->word127 = __le16_to_cpu(id->word127);
id->dlf = __le16_to_cpu(id->dlf);
id->csfo = __le16_to_cpu(id->csfo);
- for (i=0; i<31; i++)
+ for (i = 0; i < 30; i++)
id->words130_159[i] = __le16_to_cpu(id->words130_159[i]);
- for (i=0; i<97; i++)
+ for (i = 0; i < 96; i++)
id->words160_255[i] = __le16_to_cpu(id->words160_255[i]);
}
+++ /dev/null
-/*
- * $Id: totalmp.c,v 1.6 1999/08/31 06:54:10 davem Exp $
- *
- * Support for Total Impact's TotalMP PowerPC accelerator board.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/openpic.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-
-extern void totalmp_init(void);
-
-extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
- u_int field);
-void __init totalmp_init(void)
-{
- struct pci_dev *dev;
- u32 val;
- unsigned long ctl_area, ctl_area_phys;
-
- /* it's a pci card */
- if ( !pci_present() ) return;
-
- /* search for a MPIC. For now, we assume
- * only one TotalMP card installed. -- Cort
- */
- for(dev=pci_devices; dev; dev=dev->next)
- {
- if ( (dev->vendor == PCI_VENDOR_ID_IBM)
- && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
- || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
- {
- break;
- }
- }
-
- if ( !dev ) return;
-
- OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
-#if 0
- if ( (ulong)OpenPIC > 0x10000000 )
- {
- printk("TotalMP: relocating base %lx -> %lx\n",
- (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
- }*/
-#endif
- OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
-
- openpic_init(0);
-
- /* put openpic in 8259-cascade mode */
- openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
- /* set ipi to highest priority */
- openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
-
- /* allocate and remap the control area to be no-cache */
- ctl_area = __get_free_pages(GFP_ATOMIC, 3);
- ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
- ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
-
- /* soft reset cpu 0 */
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
- openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
-
- /* wait for base address reg to change, signaling that cpu 0 is done */
-#define wait_for(where) { \
- udelay(100); \
- pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \
- if ( val != 0x77700000 ) \
- { \
- printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
- /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
- return; \
- } }
-
- /* tell cpu0 where the control area is */
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
- wait_for(0);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0xff000000)>>20);
- wait_for(1);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x00ff0000)>>12);
- wait_for(2);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x0000ff00)>>4);
- wait_for(3);
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
- ((ulong)ctl_area & 0x000000ff)<<4);
- wait_for(4);
-#undef wait_for
- /* wait for cpu0 to "sign-on" */
-}
-
printk("Unknown values in msr\n");
}
show_regs(regs);
- print_backtrace((unsigned long *)regs->gpr[1]);
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
#endif
+ print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
}
_exception(SIGSEGV, regs);
IOFF = 0
ISZ = 0
-TFTPIMAGE=/tftpboot/zImage.mbx
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
+TFTPIMAGE=/tftpboot/zImage.embedded
+ifdef CONFIG_8xx
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
+endif
+
+ifdef CONFIG_8260
+ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000
+OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o
+CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260
+endif
+
OBJCOPY_ARGS = -O elf32-powerpc
ifeq ($(CONFIG_MBX),y)
* not have boot monitor support for board information.
*/
#include <sys/types.h>
-#include "asm/mpc8xx.h"
+#include <linux/autoconf.h>
+#ifdef CONFIG_8xx
+#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#endif
/* IIC functions.
extern void iic_read(uint devaddr, u_char *buf, uint offset, uint count);
extern u_char aschex_to_byte(u_char *cp);
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one. This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+
static void rpx_eth(bd_t *bd, u_char *cp);
static void rpx_brate(bd_t *bd, u_char *cp);
static void rpx_memsize(bd_t *bd, u_char *cp);
bd->bi_memstart = 0;
#else
+ /* For boards without initialized EEPROM.
+ */
bd->bi_memstart = 0;
- bd->bi_memsize = (4 * 1024 * 1024);
+ bd->bi_memsize = (8 * 1024 * 1024);
bd->bi_intfreq = 48;
bd->bi_busfreq = 48;
bd->bi_baudrate = 9600;
if (num > 50)
bd->bi_busfreq /= 2;
}
+#endif /* RPXLITE || RPXCLASSIC */
+#ifdef CONFIG_BSEIP
/* Build a board information structure for the BSE ip-Engine.
* There is more to come since we will add some environment
* variables and a function to read them.
bd->bi_intfreq = 48;
bd->bi_busfreq = 48;
}
+#endif /* BSEIP */
+#ifdef CONFIG_EST8260
+void
+embed_config(bd_t *bd)
+{
+ u_char *cp;
+ int i;
+
+#if 1
+ /* This is actually provided by my boot rom. I have it
+ * here for those people that may load the kernel with
+ * a JTAG/COP tool and not the rom monitor.
+ */
+ bd->bi_baudrate = 115200;
+ bd->bi_intfreq = 200;
+ bd->bi_busfreq = 66;
+ bd->bi_cpmfreq = 66;
+ bd->bi_brgfreq = 33;
+ bd->bi_memsize = 16 * 1024 * 1024;
+#endif
+
+ cp = (u_char *)def_enet_addr;
+ for (i=0; i<6; i++) {
+ bd->bi_enetaddr[i] = *cp++;
+ }
+}
+#endif /* EST8260 */
--- /dev/null
+#include "../kernel/ppc_defs.h"
+#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/cache.h>
+
+ .text
+
+/*
+ * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
+ *
+ * Boot loader philosophy:
+ * ROM loads us to some arbitrary location
+ * Move the boot code to the link address (8M)
+ * Call decompress_kernel()
+ * Relocate the initrd, zimage and residual data to 8M
+ * Decompress the kernel to 0
+ * Jump to the kernel entry
+ * -- Cort
+ */
+ .globl start
+start:
+ bl start_
+start_:
+ mr r11,r3 /* Save pointer to residual/board data */
+ mr r25,r5 /* Save OFW pointer */
+ li r3,MSR_IP /* Establish default MSR value */
+ mtmsr r3
+
+/* check if we need to relocate ourselves to the link addr or were we
+ loaded there to begin with -- Cort */
+ lis r4,start@h
+ ori r4,r4,start@l
+ mflr r3
+ subi r3,r3,4 /* we get the nip, not the ip of the branch */
+ mr r8,r3
+ cmp 0,r3,r4
+ bne 1010f
+/* compute size of whole image in words. this should be moved to
+ * start_ldr() -- Cort
+ */
+ lis r4,start@h
+ ori r4,r4,start@l
+ lis r5,end@h
+ ori r5,r5,end@l
+ addi r5,r5,3 /* round up */
+ sub r5,r5,r4
+ srwi r5,r5,2
+ mr r7,r5
+ b start_ldr
+1010:
+/*
+ * no matter where we're loaded, move ourselves to -Ttext address
+ */
+relocate:
+ mflr r3 /* Compute code bias */
+ subi r3,r3,4
+ mr r8,r3
+ lis r4,start@h
+ ori r4,r4,start@l
+ lis r5,end@h
+ ori r5,r5,end@l
+ addi r5,r5,3 /* Round up - just in case */
+ sub r5,r5,r4 /* Compute # longwords to move */
+ srwi r5,r5,2
+ mtctr r5
+ mr r7,r5
+ li r6,0
+ subi r3,r3,4 /* Set up for loop */
+ subi r4,r4,4
+00: lwzu r5,4(r3)
+ stwu r5,4(r4)
+ xor r6,r6,r5
+ bdnz 00b
+ lis r3,start_ldr@h
+ ori r3,r3,start_ldr@l
+ mtlr r3 /* Easiest way to do an absolute jump */
+ blr
+start_ldr:
+/* Clear all of BSS */
+ lis r3,edata@h
+ ori r3,r3,edata@l
+ lis r4,end@h
+ ori r4,r4,end@l
+ subi r3,r3,4
+ subi r4,r4,4
+ li r0,0
+50: stwu r0,4(r3)
+ cmp 0,r3,r4
+ bne 50b
+90: mr r9,r1 /* Save old stack pointer (in case it matters) */
+ lis r1,.stack@h
+ ori r1,r1,.stack@l
+ addi r1,r1,4096*2
+ subi r1,r1,256
+ li r2,0x000F /* Mask pointer to 16-byte boundary */
+ andc r1,r1,r2
+/* Run loader */
+ mr r3,r8 /* Load point */
+ mr r4,r7 /* Program length */
+ mr r5,r6 /* Checksum */
+ mr r6,r11 /* Residual data */
+ mr r7,r25 /* OFW interfaces */
+ bl decompress_kernel
+
+ /* changed to use r3 (as firmware does) for kernel
+ as ptr to residual -- Cort*/
+ lis r6,cmd_line@h
+ ori r6,r6,cmd_line@l
+ lwz r6, 0(r6)
+ subi r7,r6,1
+00: lbzu r2,1(r7)
+ cmpi 0,r2,0
+ bne 00b
+
+ /* r4,r5 have initrd_start, size */
+ lis r2,initrd_start@h
+ ori r2,r2,initrd_start@l
+ lwz r4,0(r2)
+ lis r2,initrd_end@h
+ ori r2,r2,initrd_end@l
+ lwz r5,0(r2)
+
+ /* tell kernel we're prep */
+ /*
+ * get start address of kernel code which is stored as a coff
+ * entry. see boot/head.S -- Cort
+ */
+ li r9,0x4
+ mtlr r9
+ lis r10,0xdeadc0de@h
+ ori r10,r10,0xdeadc0de@l
+ li r9,0
+ stw r10,0(r9)
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+ li r8,0
+ mtspr DBAT0U,r8
+ mtspr DBAT1U,r8
+ mtspr DBAT2U,r8
+ mtspr DBAT3U,r8
+ mtspr IBAT0U,r8
+ mtspr IBAT1U,r8
+ mtspr IBAT2U,r8
+ mtspr IBAT3U,r8
+
+ blr
+hang:
+ b hang
+
+/*
+ * Delay for a number of microseconds
+ * -- Use the BUS timer (assumes 66MHz)
+ */
+ .globl udelay
+udelay:
+ mfspr r4,PVR
+ srwi r4,r4,16
+ cmpi 0,r4,1 /* 601 ? */
+ bne .udelay_not_601
+00: li r0,86 /* Instructions / microsecond? */
+ mtctr r0
+10: addi r0,r0,0 /* NOP */
+ bdnz 10b
+ subic. r3,r3,1
+ bne 00b
+ blr
+
+.udelay_not_601:
+ mulli r4,r3,1000 /* nanoseconds */
+ addi r4,r4,59
+ li r5,60
+ divw r4,r4,r5 /* BUS ticks */
+1: mftbu r5
+ mftb r6
+ mftbu r7
+ cmp 0,r5,r7
+ bne 1b /* Get [synced] base time */
+ addc r9,r6,r4 /* Compute end time */
+ addze r8,r5
+2: mftbu r5
+ cmp 0,r5,r8
+ blt 2b
+ bgt 3f
+ mftb r6
+ cmp 0,r6,r9
+ blt 2b
+3: blr
+
+.globl _get_HID0
+_get_HID0:
+ mfspr r3,HID0
+ blr
+
+.globl _put_HID0
+_put_HID0:
+ mtspr HID0,r3
+ blr
+
+.globl _get_MSR
+_get_MSR:
+ mfmsr r3
+ blr
+
+.globl _put_MSR
+_put_MSR:
+ mtmsr r3
+ blr
+
+/*
+ * Flush instruction cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_instruction_cache)
+ mflr r5
+ bl flush_data_cache
+ mfspr r3,HID0 /* Caches are controlled by this register */
+ li r4,0
+ ori r4,r4,(HID0_ICE|HID0_ICFI)
+ or r3,r3,r4 /* Need to enable+invalidate to clear */
+ mtspr HID0,r3
+ andc r3,r3,r4
+ ori r3,r3,HID0_ICE /* Enable cache */
+ mtspr HID0,r3
+ mtlr r5
+ blr
+
+#define NUM_CACHE_LINES 128*8
+#define CACHE_LINE_SIZE 32
+#define cache_flush_buffer 0x1000
+
+/*
+ * Flush data cache
+ * *** I'm really paranoid here!
+ */
+_GLOBAL(flush_data_cache)
+ lis r3,cache_flush_buffer@h
+ ori r3,r3,cache_flush_buffer@l
+ li r4,NUM_CACHE_LINES
+ mtctr r4
+00: lwz r4,0(r3)
+ addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
+ bdnz 00b
+10: blr
+ .comm .stack,4096*2,4
*/
while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
+ /* Remove any microcode patches. We will install our own
+ * later.
+ */
+ cp->cp_cpmcr1 = 0;
+ cp->cp_cpmcr2 = 0;
+ cp->cp_cpmcr3 = 0;
+ cp->cp_cpmcr4 = 0;
+ cp->cp_rccr = 0;
+
iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
i2c = (i2c8xx_t *)&(immap->im_i2c);
--- /dev/null
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on SMC1.
+ */
+#include <linux/types.h>
+#include <linux/autoconf.h>
+#include "asm/mpc8260.h"
+#include "asm/cpm_8260.h"
+
+uint no_print;
+extern char *params[];
+extern int nparams;
+static u_char cons_hold[128], *sgptr;
+static int cons_hold_cnt;
+
+void
+serial_init(bd_t *bd)
+{
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile immap_t *ip;
+ volatile iop8260_t *io;
+ volatile cpm8260_t *cp;
+ uint dpaddr, memaddr;
+
+ ip = (immap_t *)IMAP_ADDR;
+
+ sp = (smc_t*)&(ip->im_smc[0]);
+ *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
+ up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
+
+ cp = &ip->im_cpm;
+ io = &ip->im_ioport;
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Use Port D for SMC1 instead of other functions.
+ */
+ io->iop_ppard |= 0x00c00000;
+ io->iop_pdird |= 0x00400000;
+ io->iop_pdird &= ~0x00800000;
+ io->iop_psord &= ~0x00c00000;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ */
+ dpaddr = 0x0800;
+
+ /* Grab a few bytes from the top of memory.
+ */
+#if 1
+ memaddr = (bd->bi_memsize - 256) & ~15;
+#else
+ memaddr = 0x0f002c00;
+#endif
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = memaddr;
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = memaddr+128;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* Set up the baud rate generator.
+ */
+ ip->im_clkrst.car_sccr = 0; /* DIV 4 BRG */
+ ip->im_cpmux.cmx_smr = 0;
+ ip->im_brgc1 =
+ ((((bd->bi_brgfreq * 1000000)/16) / bd->bi_baudrate) << 1) |
+ CPM_BRG_EN;
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+#if 0
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+#else
+ up->smc_mrblr = 128;
+ up->smc_maxidl = 8;
+#endif
+
+ /* Initialize Tx/Rx parameters.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+void
+serial_putchar(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+ extern bd_t *board_info;
+
+ ip = (immap_t *)IMAP_ADDR;
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+char
+serial_getc()
+{
+ char c;
+
+ if (cons_hold_cnt <= 0) {
+ cons_hold_cnt = serial_readbuf(cons_hold);
+ sgptr = cons_hold;
+ }
+ c = *sgptr++;
+ cons_hold_cnt--;
+
+ return(c);
+}
+
+int
+serial_readbuf(u_char *cbuf)
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+ int i, nc;
+
+ ip = (immap_t *)IMAP_ADDR;
+
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ nc = rbdf->cbd_datlen;
+ for (i=0; i<nc; i++)
+ *cbuf++ = *buf++;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(nc);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+ volatile immap_t *ip;
+
+ ip = (immap_t *)IMAP_ADDR;
+ up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
+ rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
#ifdef CONFIG_8xx
#include <asm/mpc8xx.h>
#endif
+#ifdef CONFIG_8260
+#include <asm/mpc8260.h>
+#endif
/*
* Please send me load/board info and such data for hardware not
unsigned long i;
char *dp;
+#ifdef CONFIG_8260
+ /* I don't know why I didn't do it this way on the 8xx.......
+ */
+ embed_config(bp);
+ serial_init(bp);
+#endif
+
/* These values must be variables. If not, the compiler optimizer
* will remove some code, causing the size of the code to vary
* when these values are zero. This is bad because we first
/* Stand alone funtions for QSpan Tundra support.
*/
-#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/mpc8xx.h>
* I don't know what to do about interrupts (yet).
*/
-#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/pci.h>
#include <asm/mpc8xx.h>
pte = find_pte(current->mm, address);
if (pte)
- return((unsigned long)(pte_page(*pte)) | (address & ~(PAGE_MASK-1)));
+ return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK-1)));
return (0);
}
printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
(long)pgd, (long)pte, (long)pte_val(*pte));
#define pp ((long)pte_val(*pte))
- printk(" RPN: %05x PP: %x SPS: %x SH: %lx "
+ printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
"CI: %lx v: %lx\n",
pp>>12, /* rpn */
(pp>>10)&3, /* pp */
#include <asm/mmu.h>
#include <asm/residual.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
+#endif
+#ifdef CONFIG_8260
+#include <asm/immap_8260.h>
+#include <asm/mpc8260.h>
+#endif
#include <asm/smp.h>
#include <asm/bootx.h>
#include <asm/machdep.h>
#ifdef CONFIG_4xx
unsigned long *oak_find_end_of_memory(void);
#endif
+#ifdef CONFIG_8260
+unsigned long *m8260_find_end_of_memory(void);
+#endif /* CONFIG_8260 */
static void mapin_ram(void);
void map_page(unsigned long va, unsigned long pa, int flags);
extern void die_if_kernel(char *,struct pt_regs *,long);
* don't get ASID compares on kernel space.
*/
f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
-#ifdef CONFIG_KGDB
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
/* Allows stub to set breakpoints everywhere */
f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
#else
mtspr(SPRN_ICCR, 0x80000000); /* 128 MB of instr. space at 0x0. */
}
#else
+ /* How about ppc_md.md_find_end_of_memory instead of these
+ * ifdefs? -- Dan.
+ */
void __init MMU_init(void)
{
if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
else if ( _machine == _MACH_gemini )
end_of_DRAM = gemini_find_end_of_memory();
#endif /* CONFIG_GEMINI */
+#if defined(CONFIG_8260)
+ else
+ end_of_DRAM = m8260_find_end_of_memory();
+#else
else /* prep */
end_of_DRAM = prep_find_end_of_memory();
+#endif
if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
hash_init();
setbat(0, base, base, 0x100000, IO_PAGE);
}
#endif
-#if 0
-// This is bogus, BAT must be aligned.
-// setbat(0, disp_bi->dispDeviceBase, disp_bi->dispDeviceBase, 0x100000, IO_PAGE);
-// disp_bi->logicalDisplayBase = disp_bi->dispDeviceBase;
-#endif
ioremap_base = 0xf0000000;
break;
case _MACH_apus:
setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
break;
+ case _MACH_8260:
+ /* Map the IMMR, plus anything else we can cover
+ * in that upper space according to the memory controller
+ * chip select mapping. Grab another bunch of space
+ * below that for stuff we can't cover in the upper.
+ */
+ setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+ setbat(1, 0xe0000000, 0xe0000000, 0x10000000, IO_PAGE);
+ ioremap_base = 0xe0000000;
+ break;
}
ioremap_bot = ioremap_base;
#else /* CONFIG_8xx */
}
#endif /* defined(CONFIG_GEMINI) */
+#ifdef CONFIG_8260
+/*
+ * Same hack as 8xx.
+ */
+unsigned long __init *m8260_find_end_of_memory(void)
+{
+ bd_t *binfo;
+ unsigned long *ret;
+ extern unsigned char __res[];
+
+ binfo = (bd_t *)__res;
+
+ phys_mem.regions[0].address = 0;
+ phys_mem.regions[0].size = binfo->bi_memsize;
+ phys_mem.n_regions = 1;
+
+ ret = __va(phys_mem.regions[0].size);
+ set_phys_avail(&phys_mem);
+ return ret;
+}
+#endif /* CONFIG_8260 */
+
#ifdef CONFIG_APUS
#define HARDWARE_MAPPED_SIZE (512*1024)
unsigned long __init *apus_find_end_of_memory(void)
case 3: /* 603 */
case 6: /* 603e */
case 7: /* 603ev */
+ case 0x0081: /* 82xx */
Hash_size = 0;
Hash_mask = 0;
break;
# Makefile for xmon
O_TARGET = x.o
+ifeq ($(CONFIG_8xx),y)
+O_OBJS = start_8xx.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+else
O_OBJS = start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+endif
include $(TOPDIR)/Rules.make
GSETSPR(275, sprg3)
GSETSPR(282, ear)
GSETSPR(287, pvr)
+#ifndef CONFIG_8xx
GSETSPR(528, bat0u)
GSETSPR(529, bat0l)
GSETSPR(530, bat1u)
GSETSPR(1010, iabr)
GSETSPR(1013, dabr)
GSETSPR(1023, pir)
+#else
+GSETSPR(144, cmpa)
+GSETSPR(145, cmpb)
+GSETSPR(146, cmpc)
+GSETSPR(147, cmpd)
+GSETSPR(158, ictrl)
+#endif
static inline int get_sr(int n)
{
sccd[3] &= ~0x80; /* reset DLAB */
}
+extern int adb_init(void);
+
void
xmon_map_scc(void)
{
/* needs to be hacked if xmon_printk is to be used
from within find_via_pmu() */
+#ifdef CONFIG_ADB_PMU
if (!via_modem && disp_bi && find_via_pmu()) {
prom_drawstring("xmon uses screen and keyboard\n");
use_screen = 1;
- return;
}
#endif
+#endif
#ifdef CHRP_ESCC
addr = 0xc1013020;
np = find_devices("mac-io");
if (np && np->n_addrs) {
macio_node = np;
- addr = np->addrs[0].address + 0x13000;
- /* use the B channel on the iMac */
- if (!xmon_use_sccb)
- addr += 0x20; /* use A channel */
+ addr = np->addrs[0].address + 0x13020;
}
base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
sccc = base + (addr & ~PAGE_MASK);
-#ifdef CHRP_ESCC
- sccd = sccc + (0xc1013030 - 0xc1013020);
-#else
- sccd = sccc + (0xf3013030 - 0xf3013020);
-#endif
+ sccd = sccc + 0x10;
}
else if ( _machine & _MACH_gemini )
{
ct = 0;
for (i = 0; i < nb; ++i) {
while ((*sccc & TXRDY) == 0) {
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
-#endif /* CONFIG_ADB */
+#endif /* CONFIG_ADB_PMU */
}
c = p[i];
if (c == '\n' && !ct) {
ct = 1;
--i;
} else {
- prom_drawchar(c);
if (console)
printk("%c", c);
ct = 0;
}
int xmon_wants_key;
-int xmon_pmu_keycode;
+int xmon_adb_keycode;
#ifdef CONFIG_BOOTX_TEXT
-static int xmon_pmu_shiftstate;
+static int xmon_adb_shiftstate;
static unsigned char xmon_keytab[128] =
"asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
"\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
static int
-xmon_get_pmu_key(void)
+xmon_get_adb_key(void)
{
int k, t, on;
xmon_wants_key = 1;
for (;;) {
- xmon_pmu_keycode = -1;
+ xmon_adb_keycode = -1;
t = 0;
on = 0;
do {
prom_drawchar('\b');
t = 200000;
}
+#ifdef CONFIG_ADB_PMU
pmu_poll();
- } while (xmon_pmu_keycode == -1);
- k = xmon_pmu_keycode;
+#endif /* CONFIG_ADB_PMU */
+ } while (xmon_adb_keycode == -1);
+ k = xmon_adb_keycode;
if (on)
prom_drawstring(" \b");
/* test for shift keys */
if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
- xmon_pmu_shiftstate = (k & 0x80) == 0;
+ xmon_adb_shiftstate = (k & 0x80) == 0;
continue;
}
if (k >= 0x80)
continue; /* ignore up transitions */
- k = (xmon_pmu_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
+ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
if (k != 0)
break;
}
#ifdef CONFIG_BOOTX_TEXT
if (use_screen) {
for (i = 0; i < nb; ++i)
- *p++ = xmon_get_pmu_key();
+ *p++ = xmon_get_adb_key();
return i;
}
#endif
xmon_init_scc();
for (i = 0; i < nb; ++i) {
while ((*sccc & RXRDY) == 0)
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
#else
;
-#endif /* CONFIG_ADB */
+#endif /* CONFIG_ADB_PMU */
buf_access();
*p++ = *sccd;
}
xmon_read_poll(void)
{
if ((*sccc & RXRDY) == 0) {
-#ifdef CONFIG_ADB
+#ifdef CONFIG_ADB_PMU
if (sys_ctrler == SYS_CTRLER_PMU)
pmu_poll();
-#else
- ;
-#endif
+#endif /* CONFIG_ADB_PMU */
return -1;
}
buf_access();
while (readtb() - t0 < 3*TB_SPEED)
eieio();
}
+ /* use the B channel if requested */
+ if (xmon_use_sccb) {
+ sccc = (volatile unsigned char *)
+ ((unsigned long)sccc & ~0x20);
+ sccd = sccc + 0x10;
+ }
for (i = 20000; i != 0; --i) {
x = *sccc; eieio();
}
--- /dev/null
+/*
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 2000 Dan Malek.
+ * Quick hack of Paul's code to make XMON work on 8xx processors. Lots
+ * of assumptions, like the SMC1 is used, it has been initialized by the
+ * loader at some point, and we can just stuff and suck bytes.
+ * We rely upon the 8xx uart driver to support us, as the interface
+ * changes between boot up and operational phases of the kernel.
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <linux/kernel.h>
+#include <asm/processor.h>
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+#include "commproc.h"
+
+extern void xmon_printf(const char *fmt, ...);
+extern int xmon_8xx_write(char *str, int nb);
+extern int xmon_8xx_read_poll(void);
+extern int xmon_8xx_read_char(void);
+void prom_drawhex(uint);
+void prom_drawstring(const char *str);
+
+static int use_screen = 1; /* default */
+
+#define TB_SPEED 25000000
+
+static inline unsigned int readtb(void)
+{
+ unsigned int ret;
+
+ asm volatile("mftb %0" : "=r" (ret) :);
+ return ret;
+}
+
+void buf_access(void)
+{
+}
+
+void
+xmon_map_scc(void)
+{
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+ use_screen = 0;
+
+ prom_drawstring("xmon uses serial port\n");
+}
+
+static int scc_initialized = 0;
+
+void xmon_init_scc(void);
+
+int
+xmon_write(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i, c, ct;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ return(xmon_8xx_write(ptr, nb));
+}
+
+int xmon_wants_key;
+
+int
+xmon_read(void *handle, void *ptr, int nb)
+{
+ char *p = ptr;
+ int i;
+
+ if (!scc_initialized)
+ xmon_init_scc();
+
+ for (i = 0; i < nb; ++i) {
+ *p++ = xmon_8xx_read_char();
+ }
+ return i;
+}
+
+int
+xmon_read_poll(void)
+{
+ return(xmon_8xx_read_poll());
+}
+
+void
+xmon_init_scc()
+{
+ scc_initialized = 1;
+}
+
+#if 0
+extern int (*prom_entry)(void *);
+
+int
+xmon_exit(void)
+{
+ struct prom_args {
+ char *service;
+ } args;
+
+ for (;;) {
+ args.service = "exit";
+ (*prom_entry)(&args);
+ }
+}
+#endif
+
+void *xmon_stdin;
+void *xmon_stdout;
+void *xmon_stderr;
+
+void
+xmon_init(void)
+{
+}
+
+int
+xmon_putc(int c, void *f)
+{
+ char ch = c;
+
+ if (c == '\n')
+ xmon_putc('\r', f);
+ return xmon_write(f, &ch, 1) == 1? c: -1;
+}
+
+int
+xmon_putchar(int c)
+{
+ return xmon_putc(c, xmon_stdout);
+}
+
+int
+xmon_fputs(char *str, void *f)
+{
+ int n = strlen(str);
+
+ return xmon_write(f, str, n) == n? 0: -1;
+}
+
+int
+xmon_readchar(void)
+{
+ char ch;
+
+ for (;;) {
+ switch (xmon_read(xmon_stdin, &ch, 1)) {
+ case 1:
+ return ch;
+ case -1:
+ xmon_printf("read(stdin) returned -1\r\n", 0, 0);
+ return -1;
+ }
+ }
+}
+
+static char line[256];
+static char *lineptr;
+static int lineleft;
+
+#if 0
+int xmon_expect(const char *str, unsigned int timeout)
+{
+ int c;
+ unsigned int t0;
+
+ timeout *= TB_SPEED;
+ t0 = readtb();
+ do {
+ lineptr = line;
+ for (;;) {
+ c = xmon_read_poll();
+ if (c == -1) {
+ if (readtb() - t0 > timeout)
+ return 0;
+ continue;
+ }
+ if (c == '\n')
+ break;
+ if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+ *lineptr++ = c;
+ }
+ *lineptr = 0;
+ } while (strstr(line, str) == NULL);
+ return 1;
+}
+#endif
+
+int
+xmon_getchar(void)
+{
+ int c;
+
+ if (lineleft == 0) {
+ lineptr = line;
+ for (;;) {
+ c = xmon_readchar();
+ if (c == -1 || c == 4)
+ break;
+ if (c == '\r' || c == '\n') {
+ *lineptr++ = '\n';
+ xmon_putchar('\n');
+ break;
+ }
+ switch (c) {
+ case 0177:
+ case '\b':
+ if (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ case 'U' & 0x1F:
+ while (lineptr > line) {
+ xmon_putchar('\b');
+ xmon_putchar(' ');
+ xmon_putchar('\b');
+ --lineptr;
+ }
+ break;
+ default:
+ if (lineptr >= &line[sizeof(line) - 1])
+ xmon_putchar('\a');
+ else {
+ xmon_putchar(c);
+ *lineptr++ = c;
+ }
+ }
+ }
+ lineleft = lineptr - line;
+ lineptr = line;
+ }
+ if (lineleft == 0)
+ return -1;
+ --lineleft;
+ return *lineptr++;
+}
+
+char *
+xmon_fgets(char *str, int nb, void *f)
+{
+ char *p;
+ int c;
+
+ for (p = str; p < str + nb - 1; ) {
+ c = xmon_getchar();
+ if (c == -1) {
+ if (p == str)
+ return 0;
+ break;
+ }
+ *p++ = c;
+ if (c == '\n')
+ break;
+ }
+ *p = 0;
+ return str;
+}
+
+void
+prom_drawhex(uint val)
+{
+ unsigned char buf[10];
+
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789abcdef"[val & 0x0f];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ xmon_fputs(buf, xmon_stdout);
+}
+
+void
+prom_drawstring(const char *str)
+{
+ xmon_fputs(str, xmon_stdout);
+}
xmon(struct pt_regs *excp)
{
struct pt_regs regs;
- int msr, cmd, i;
- unsigned *sp;
+ int msr, cmd;
if (excp == NULL) {
asm volatile ("stw 0,0(%0)\n\
excp = ®s;
}
- prom_drawstring("xmon pc="); prom_drawhex(excp->nip);
- prom_drawstring(" lr="); prom_drawhex(excp->link);
- prom_drawstring(" msr="); prom_drawhex(excp->msr);
- prom_drawstring(" trap="); prom_drawhex(excp->trap);
- prom_drawstring(" sp="); prom_drawhex(excp->gpr[1]);
- sp = (unsigned *)&excp->gpr[0];
- for (i = 0; i < 32; ++i) {
- if ((i & 7) == 0)
- prom_drawstring("\n");
- prom_drawstring(" ");
- prom_drawhex(sp[i]);
- }
- sp = (unsigned *) excp->gpr[1];
- for (i = 0; i < 64; ++i) {
- if ((i & 7) == 0) {
- prom_drawstring("\n");
- prom_drawhex(sp);
- prom_drawstring(" ");
- }
- prom_drawstring(" ");
- prom_drawhex(sp[i]);
- }
- prom_drawstring("\n");
msr = get_msr();
set_msr(msr & ~0x8000); /* disable interrupts */
remove_bpts();
bp->enabled = 0;
}
}
+#ifndef CONFIG_8xx
if (dabr.enabled)
set_dabr(dabr.address);
if (iabr.enabled)
set_iabr(iabr.address);
+#endif
}
static void
struct bpt *bp;
unsigned instr;
+#ifndef CONFIG_8xx
set_dabr(0);
set_iabr(0);
+#endif
bp = bpts;
for (i = 0; i < NBPTS; ++i, ++bp) {
if (!bp->enabled)
cmd = inchar();
switch (cmd) {
+#ifndef CONFIG_8xx
case 'd':
mode = 7;
cmd = inchar();
iabr.address |= 3;
scanhex(&iabr.count);
break;
+#endif
case 'c':
if (!scanhex(&a)) {
/* clear all breakpoints */
return NULL;
#if 0
cmp = simple_strtoul(c, &c, 8);
+ /* XXX crap, we don't want the whole of the rest of the map - paulus */
strcpy( last, strsep( &c, "\n"));
while ( c < (sysmap+sysmap_size) )
{
break;
strcpy( last, strsep( &c, "\n"));
}
- return NULLlast;
+ return last;
#endif
}
}
typedef void (*timeout_fn)(unsigned long);
-static struct timer_list fd_timeout ={ NULL, NULL, 0, 0,
- (timeout_fn) floppy_shutdown };
+static struct timer_list fd_timeout ={ function: (timeout_fn) floppy_shutdown };
static const char *timeout_message;
static void is_alive(const char *message)
{
/* this routine checks whether the floppy driver is "alive" */
- if (fdc_busy && command_status < 2 && !fd_timeout.prev){
+ if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){
DPRINT("timeout handler died: %s\n",message);
}
}
}
static struct timer_list motor_off_timer[N_DRIVE] = {
- { NULL, NULL, 0, 0, motor_off_callback },
- { NULL, NULL, 0, 1, motor_off_callback },
- { NULL, NULL, 0, 2, motor_off_callback },
- { NULL, NULL, 0, 3, motor_off_callback },
- { NULL, NULL, 0, 4, motor_off_callback },
- { NULL, NULL, 0, 5, motor_off_callback },
- { NULL, NULL, 0, 6, motor_off_callback },
- { NULL, NULL, 0, 7, motor_off_callback }
+ { data: 0, function: motor_off_callback },
+ { data: 1, function: motor_off_callback },
+ { data: 2, function: motor_off_callback },
+ { data: 3, function: motor_off_callback },
+ { data: 4, function: motor_off_callback },
+ { data: 5, function: motor_off_callback },
+ { data: 6, function: motor_off_callback },
+ { data: 7, function: motor_off_callback }
};
/* schedules motor off */
mark_bh(IMMEDIATE_BH);
}
-static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
+static struct timer_list fd_timer;
static void cancel_activity(void)
{
printk("DEVICE_INTR=%p\n", DEVICE_INTR);
if (floppy_tq.sync)
printk("floppy_tq.routine=%p\n", floppy_tq.routine);
- if (fd_timer.prev)
+ if (timer_pending(&fd_timer))
printk("fd_timer.function=%p\n", fd_timer.function);
- if (fd_timeout.prev){
+ if (timer_pending(&fd_timeout)){
printk("timer_table=%p\n",fd_timeout.function);
printk("expires=%lu\n",fd_timeout.expires-jiffies);
printk("now=%lu\n",jiffies);
#ifdef FLOPPY_SANITY_CHECK
#ifndef __sparc__
for (drive=0; drive < N_FDC * 4; drive++)
- if (motor_off_timer[drive].next)
+ if (timer_pending(motor_off_timer + drive))
printk("motor off timer %d still active\n", drive);
#endif
- if (fd_timeout.next)
+ if (timer_pending(&fd_timeout))
printk("floppy timer still active:%s\n", timeout_message);
- if (fd_timer.next)
+ if (timer_pending(&fd_timer))
printk("auxiliary floppy timer still active\n");
if (floppy_tq.sync)
printk("task queue still active\n");
lo->lo_backing_file->f_flags = file->f_flags;
lo->lo_backing_file->f_owner = file->f_owner;
lo->lo_backing_file->f_dentry = file->f_dentry;
+ lo->lo_backing_file->f_vfsmnt = file->f_vfsmnt;
lo->lo_backing_file->f_op = file->f_op;
lo->lo_backing_file->private_data = file->private_data;
file_moveto(lo->lo_backing_file, file);
* 1.10 Paul Barton-Davis: add support for async I/O
* 1.10a Andrea Arcangeli: Alpha updates
* 1.10b Andrew Morton: SMP lock fix
+ * 1.10c Cesar Barros: SMP locking fixes and cleanup
*/
-#define RTC_VERSION "1.10b"
+#define RTC_VERSION "1.10c"
#define RTC_IRQ 8 /* Can't see this changing soon. */
#define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */
#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
#define RTC_TIMER_ON 0x02 /* missed irq timer active */
-static atomic_t rtc_status = ATOMIC_INIT(0); /* bitmapped status byte. */
+/*
+ * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
+ * protected by the big kernel lock. However, ioctl can still disable the timer
+ * in rtc_status and then with del_timer after the interrupt has read
+ * rtc_status but before mod_timer is called, which would then reenable the
+ * timer (but you would need to have an awful timing before you'd trip on it)
+ */
+static unsigned long rtc_status = 0; /* bitmapped status byte. */
static unsigned long rtc_freq = 0; /* Current periodic IRQ rate */
static unsigned long rtc_irq_data = 0; /* our output to the world */
rtc_irq_data += 0x100;
rtc_irq_data &= ~0xff;
rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
+
+ if (rtc_status & RTC_TIMER_ON)
+ mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
+
spin_unlock (&rtc_lock);
+ /* Now do the rest of the actions */
wake_up_interruptible(&rtc_wait);
if (rtc_async_queue)
kill_fasync (rtc_async_queue, SIGIO, POLL_IN);
-
- if (atomic_read(&rtc_status) & RTC_TIMER_ON)
- mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
}
#endif
current->state = TASK_INTERRUPTIBLE;
- while ((data = xchg(&rtc_irq_data, 0)) == 0) {
+ do {
+ /* First make it right. Then make it fast. Putting this whole
+ * block within the parentheses of a while would be too
+ * confusing. And no, xchg() is not the answer. */
+ spin_lock_irq (&rtc_lock);
+ data = rtc_irq_data;
+ rtc_irq_data = 0;
+ spin_unlock_irq (&rtc_lock);
+
+ if (data != 0)
+ break;
+
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
goto out;
goto out;
}
schedule();
- }
+ } while (1);
retval = put_user(data, (unsigned long *)buf);
if (!retval)
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
-
- unsigned long flags;
struct rtc_time wtime;
switch (cmd) {
case RTC_PIE_OFF: /* Mask periodic int. enab. bit */
{
mask_rtc_irq_bit(RTC_PIE);
- if (atomic_read(&rtc_status) & RTC_TIMER_ON) {
+ if (rtc_status & RTC_TIMER_ON) {
+ spin_lock_irq (&rtc_lock);
+ rtc_status &= ~RTC_TIMER_ON;
del_timer(&rtc_irq_timer);
- atomic_set(&rtc_status,
- atomic_read(&rtc_status) & ~RTC_TIMER_ON);
+ spin_unlock_irq (&rtc_lock);
}
return 0;
}
if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
return -EACCES;
- if (!(atomic_read(&rtc_status) & RTC_TIMER_ON)) {
- atomic_set(&rtc_status,
- atomic_read(&rtc_status) | RTC_TIMER_ON);
+ if (!(rtc_status & RTC_TIMER_ON)) {
+ spin_lock_irq (&rtc_lock);
rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
add_timer(&rtc_irq_timer);
+ rtc_status |= RTC_TIMER_ON;
+ spin_unlock_irq (&rtc_lock);
}
set_rtc_irq_bit(RTC_PIE);
return 0;
if (sec >= 60)
sec = 0xff;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
RTC_ALWAYS_BCD)
{
CMOS_WRITE(hrs, RTC_HOURS_ALARM);
CMOS_WRITE(min, RTC_MINUTES_ALARM);
CMOS_WRITE(sec, RTC_SECONDS_ALARM);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
return 0;
}
unsigned char mon, day, hrs, min, sec, leap_yr;
unsigned char save_control, save_freq_select;
unsigned int yrs;
- unsigned long flags;
-
+
if (!capable(CAP_SYS_TIME))
return -EACCES;
if ((yrs -= epoch) > 255) /* They are unsigned */
return -EINVAL;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
if (yrs > 169) {
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
return -EINVAL;
}
if (yrs >= 100)
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
return 0;
}
#ifndef __alpha__
if (arg != (1<<tmp))
return -EINVAL;
+ spin_lock_irq(&rtc_lock);
rtc_freq = arg;
- spin_lock_irqsave(&rtc_lock, flags);
val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
val |= (16 - tmp);
CMOS_WRITE(val, RTC_FREQ_SELECT);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
return 0;
}
#else
static int rtc_open(struct inode *inode, struct file *file)
{
- unsigned long flags;
-
- if(atomic_read(&rtc_status) & RTC_IS_OPEN)
+ /* If someday somebody decides to remove the kernel_lock on open and
+ * close and ioctl this is gonna get open to races */
+ if(rtc_status & RTC_IS_OPEN)
return -EBUSY;
MOD_INC_USE_COUNT;
- atomic_set(&rtc_status, atomic_read(&rtc_status) | RTC_IS_OPEN);
+ rtc_status |= RTC_IS_OPEN;
- spin_lock_irqsave (&rtc_lock, flags);
+ spin_lock_irq (&rtc_lock);
rtc_irq_data = 0;
- spin_unlock_irqrestore (&rtc_lock, flags);
+ spin_unlock_irq (&rtc_lock);
return 0;
}
static int rtc_release(struct inode *inode, struct file *file)
{
- unsigned long flags;
#ifndef __alpha__
/*
* Turn off all interrupts once the device is no longer
unsigned char tmp;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
tmp = CMOS_READ(RTC_CONTROL);
tmp &= ~RTC_PIE;
tmp &= ~RTC_AIE;
tmp &= ~RTC_UIE;
CMOS_WRITE(tmp, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
- spin_unlock_irqrestore(&rtc_lock, flags);
- if (atomic_read(&rtc_status) & RTC_TIMER_ON) {
- atomic_set(&rtc_status, atomic_read(&rtc_status) & ~RTC_TIMER_ON);
+ if (rtc_status & RTC_TIMER_ON) {
+ rtc_status &= ~RTC_TIMER_ON;
del_timer(&rtc_irq_timer);
}
+ spin_unlock_irq(&rtc_lock);
if (file->f_flags & FASYNC) {
rtc_fasync (-1, file, 0);
#endif
MOD_DEC_USE_COUNT;
- spin_lock_irqsave (&rtc_lock, flags);
+ spin_lock_irq (&rtc_lock);
rtc_irq_data = 0;
- spin_unlock_irqrestore (&rtc_lock, flags);
- atomic_set(&rtc_status, atomic_read(&rtc_status) & ~RTC_IS_OPEN);
+ spin_unlock_irq (&rtc_lock);
+ rtc_status = rtc_status & ~RTC_IS_OPEN;
return 0;
}
/* Called without the kernel lock - fine */
static unsigned int rtc_poll(struct file *file, poll_table *wait)
{
- unsigned long l, flags;
+ unsigned long l;
poll_wait(file, &rtc_wait, wait);
- spin_lock_irqsave (&rtc_lock, flags);
+ spin_lock_irq (&rtc_lock);
l = rtc_irq_data;
- spin_unlock_irqrestore (&rtc_lock, flags);
+ spin_unlock_irq (&rtc_lock);
if (l != 0)
return POLLIN | POLLRDNORM;
static int __init rtc_init(void)
{
- unsigned long flags;
#ifdef __alpha__
unsigned int year, ctrl;
unsigned long uip_watchdog;
while (jiffies - uip_watchdog < 2*HZ/100)
barrier();
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
year = CMOS_READ(RTC_YEAR);
ctrl = CMOS_READ(RTC_CONTROL);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
BCD_TO_BIN(year); /* This should never happen... */
#ifndef __alpha__
init_timer(&rtc_irq_timer);
rtc_irq_timer.function = rtc_dropped_irq;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
- spin_unlock_irqrestore(&rtc_lock, flags);
-#endif
+ spin_unlock_irq(&rtc_lock);
rtc_freq = 1024;
+#endif
printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
static void __exit rtc_exit (void)
{
/* interrupts and maybe timer disabled at this point by rtc_release */
+ /* FIXME: Maybe??? */
- if (atomic_read(&rtc_status) & RTC_TIMER_ON)
+ if (rtc_status & RTC_TIMER_ON) {
+ spin_lock_irq (&rtc_lock);
+ rtc_status &= ~RTC_TIMER_ON;
del_timer(&rtc_irq_timer);
+ spin_unlock_irq (&rtc_lock);
+
+ printk(KERN_WARNING "rtc_exit(), and timer still running.\n");
+ }
remove_proc_entry ("driver/rtc", NULL);
misc_deregister(&rtc_dev);
static void rtc_dropped_irq(unsigned long data)
{
- unsigned long flags;
-
printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq);
- mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq (&rtc_lock);
+
+ /* Just in case someone disabled the timer from behind our back... */
+ if (rtc_status & RTC_TIMER_ON)
+ mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
+
rtc_irq_data += ((rtc_freq/HZ)<<8);
rtc_irq_data &= ~0xff;
rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
+
+ /* Now we have new data */
+ wake_up_interruptible(&rtc_wait);
+
+ if (rtc_async_queue)
+ kill_fasync (rtc_async_queue, SIGIO, POLL_IN);
}
#endif
char *p;
struct rtc_time tm;
unsigned char batt, ctrl;
- unsigned long flags;
+ unsigned long freq;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
batt = CMOS_READ(RTC_VALID) & RTC_VRT;
ctrl = CMOS_READ(RTC_CONTROL);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ freq = rtc_freq;
+ spin_unlock_irq(&rtc_lock);
p = buf;
YN(RTC_AIE),
YN(RTC_UIE),
YN(RTC_PIE),
- rtc_freq,
+ freq,
batt ? "okay" : "dead");
return p - buf;
/*
* Returns true if a clock update is in progress
*/
+/* FIXME shouldn't this be above rtc_init to make it fully inlined? */
static inline unsigned char rtc_is_updating(void)
{
- unsigned long flags;
unsigned char uip;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
return uip;
}
static void get_rtc_time(struct rtc_time *rtc_tm)
{
-
- unsigned long flags, uip_watchdog = jiffies;
+ unsigned long uip_watchdog = jiffies;
unsigned char ctrl;
/*
* RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
* by the RTC when initially set to a non-zero value.
*/
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
ctrl = CMOS_READ(RTC_CONTROL);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
static void get_rtc_alm_time(struct rtc_time *alm_tm)
{
- unsigned long flags;
unsigned char ctrl;
/*
* Only the values that we read from the RTC are set. That
* means only tm_hour, tm_min, and tm_sec.
*/
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
ctrl = CMOS_READ(RTC_CONTROL);
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
{
static void mask_rtc_irq_bit(unsigned char bit)
{
unsigned char val;
- unsigned long flags;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
val = CMOS_READ(RTC_CONTROL);
val &= ~bit;
CMOS_WRITE(val, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
+
rtc_irq_data = 0;
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
}
static void set_rtc_irq_bit(unsigned char bit)
{
unsigned char val;
- unsigned long flags;
- spin_lock_irqsave(&rtc_lock, flags);
+ spin_lock_irq(&rtc_lock);
val = CMOS_READ(RTC_CONTROL);
val |= bit;
CMOS_WRITE(val, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
+
rtc_irq_data = 0;
- spin_unlock_irqrestore(&rtc_lock, flags);
+ spin_unlock_irq(&rtc_lock);
}
#endif
pdev);
if (!pdev) break;
- if (pci_enable_device(pdev)) {
- i++;
+ if (pci_enable_device(pdev))
continue;
- }
sx_board[i].irq = pdev->irq;
void
_kd_mksound(unsigned int hz, unsigned int ticks)
{
- static struct timer_list sound_timer = { NULL, NULL, 0, 0,
- kd_nosound };
+ static struct timer_list sound_timer = { function: kd_nosound };
unsigned int count = 0;
unsigned long flags;
if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
sleep = jiffies + WAIT_MIN_SLEEP;
#if 1
- if (hwgroup->timer.next || hwgroup->timer.prev)
+ if (timer_pending(&hwgroup->timer))
printk("ide_set_handler: timer already active\n");
#endif
hwgroup->sleeping = 1; /* so that ide_timer_expiry knows what to do */
#ifdef MODULE
-static char devicename[9] = { 0, };
-
static struct net_device dev_3c501 =
{
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+ "", /* device name is inserted by linux/drivers/net/net_init.c */
0, 0, 0, 0,
0x280, 5,
0, 0, 0, NULL, el1_probe
}
#ifdef MODULE
#define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */
-#define NAMELEN 8 /* #of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, };
static struct net_device dev_el2[MAX_EL2_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
struct net_device *dev = &dev_el2[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */
}
#ifdef MODULE
-#define NAMELEN 9
-static char devicename[ELP_MAX_CARDS][NAMELEN] = {{0,}};
static struct net_device dev_3c505[ELP_MAX_CARDS] =
{
- { NULL, /* device name is inserted by net_init.c */
+ { "", /* device name is inserted by net_init.c */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, elplus_probe},
for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_3c505[this_dev];
- dev->name = devicename[this_dev];
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
if (dma[this_dev]) {
lp->rx_tail = rx_tail;
}
#ifdef MODULE
-static char devicename[9] = { 0, };
static struct net_device dev_3c507 = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+ "", /* device name is inserted by linux/drivers/net/net_init.c */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, el16_probe
};
struct corkscrew_private {
- char devname[8]; /* "ethN" string, also for kernel debug. */
const char *product_name;
struct net_device *next_module;
/* The Rx and Tx rings are here to keep them quad-word-aligned. */
dev->priv =
(void *) (((long) dev + sizeof(struct net_device) + 15) & ~15);
vp = (struct corkscrew_private *) dev->priv;
- dev->name = vp->devname; /* An empty string. */
dev->base_addr = ioaddr;
dev->irq = irq;
dev->dma =
/* Increase if needed ;) */
#define MAX_3C523_CARDS 4
-/* I'm not sure where this magic 9 comes from */
-#define NAMELEN 9
-
-static char devicenames[NAMELEN * MAX_3C523_CARDS] = {0,};
static struct net_device dev_elmc[MAX_3C523_CARDS] =
{
{
- NULL /*"3c523" */ , 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL
+ "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL
},
};
for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++)
{
struct net_device *dev = &dev_elmc[this_dev];
- dev->name=devicenames+(NAMELEN*this_dev);
dev->irq=irq[this_dev];
dev->base_addr=io[this_dev];
dev->init=elmc_probe;
#ifdef MODULE
-static char devicename[9] = { 0, };
static struct net_device this_device = {
- devicename, /* will be inserted by linux/drivers/net/mc32_init.c */
+ "", /* will be inserted by linux/drivers/net/mc32_init.c */
0, 0, 0, 0,
0, 0, /* I/O address, IRQ */
0, 0, 0, NULL, mc32_probe };
Linux Kernel Additions:
+ 0.99H+lk0.9 - David S. Miller - softnet, PCI DMA updates
+ 0.99H+lk1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+ Remove compatibility defines for kernel versions < 2.2.x.
+ Update for new 2.3.x module interface
LK1.1.2 (March 19, 2000)
* New PCI interface (jgarzik)
-*/
-
-/*
- 22Apr00, Andrew Morton <andrewm@uow.edu.au>
+ LK1.1.3 25 April 2000, Andrew Morton <andrewm@uow.edu.au>
- Merged with 3c575_cb.c
- Don't set RxComplete in boomerang interrupt enable reg
- spinlock in vortex_timer to protect mdio functions
- Handle resource allocation failures.
- Fix 3CCFE575CT LED polarity
- Make tx_interrupt_mitigation the default
+
+ LK1.1.4 25 April 2000, Andrew Morton <andrewm@uow.edu.au>
- Add extra TxReset to vortex_up() to fix 575_cb hotplug initialisation probs.
+ - Put vortex_info_tbl into __devinitdata
+ - In the vortex_error StatsFull HACK, disable stats in vp->intr_enable as well
+ as in the hardware.
+ - Increased the loop counter in wait_for_completion from 2,000 to 4,000.
+
+ LK1.1.5 28 April 2000, andrewm
+ - Added powerpc defines
+ - Some extra diagnostics
+ - In vortex_error(), reset the Tx on maxCollisions. Otherwise most
+ chips usually get a Tx timeout.
+ - Added extra_reset module parm
+ - Replaced some inline timer manip with mod_timer
+ (Franois romieu <Francois.Romieu@nic.fr>)
+ - In vortex_up(), don't make Wn3_config initialisation dependent upon has_nway
+ (this came across from 3c575_cb).
+
- See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
*/
* elimination of all the tests and reduced cache footprint.
*/
-static char *version =
-"3c59x.c:v0.99L+LK1.1.2+AKPM 24 Apr 2000 Donald Becker and others http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
-
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
static const int mtu = 1500;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 32;
+/* Give the NIC an extra reset at the end of vortex_up() */
+static int extra_reset = 0;
/* Allow aggregation of Tx interrupts. Saves CPU load at the cost
* of possible Tx stalls if the system is blocking interrupts
* somewhere else. Undefine this to disable.
+ * AKPM 26 April 2000: enabling this still gets vestigial Tx timeouts
+ * in a heavily loaded (collision-prone) 10BaseT LAN. Should be OK with
+ * switched Ethernet.
*/
#define tx_interrupt_mitigation 1
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
#ifndef __OPTIMIZE__
-#warning You must compile this file with the correct options!
-#warning See the last lines of the source file.
+#error You must compile this file with the correct options!
+#error See the last lines of the source file.
#error You must compile this driver with "-O".
#endif
#include <asm/bitops.h>
#include <asm/io.h>
+/* John Daniel <jdaniel@etresoft.com> said these work... */
+#ifdef __powerpc__
+#define outsl outsl_ns
+#define insl insl_ns
+#endif
+
/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
This is only in the support-all-kernels source code. */
#include <linux/delay.h>
+static char *version __devinitdata =
+"3c59x.c:v0.99L+LK1.1.5 30 Apr 2000 Donald Becker and others http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html " "$Revision: 1.78 $\n";
+
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
MODULE_PARM(debug, "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(extra_reset, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
MODULE_PARM(compaq_device_id, "i");
int flags;
int drv_flags;
int io_size;
-} vortex_info_tbl[] = {
+} vortex_info_tbl[] __devinitdata = {
{"3c590 Vortex 10Mbps",
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
{"3c592 EISA 10mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */
/* PCI configuration space information. */
struct pci_dev *pdev;
- char *cb_fn_base; /* CardBus function status addr space. */
- int chip_id;
+ char *cb_fn_base; /* CardBus function status addr space. */
/* The remainder are related to chip state, mostly media selection. */
struct timer_list timer; /* Media selection timer. */
full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
hw_csums:1, /* Has hardware checksums. */
tx_full:1,
+ has_nway:1,
open:1;
+ int tx_reset_resume; /* Flag to retart timer after vortex_error handling */
u16 status_enable;
u16 intr_enable;
u16 available_media; /* From Wn3_Options. */
unsigned char phys[2]; /* MII device addresses. */
u16 deferred; /* Resend these interrupts when we
* bale from the ISR */
+ u16 io_size; /* Size of PCI region (for release_region) */
spinlock_t lock;
};
static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct net_device *dev);
+static void dump_tx_ring(struct net_device *dev);
static void update_stats(long ioaddr, struct net_device *dev);
static struct net_device_stats *vortex_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
dev->base_addr = ioaddr;
dev->irq = irq;
dev->mtu = mtu;
+ vp->has_nway = (vortex_info_tbl[chip_idx].drv_flags & HAS_NWAY) ? 1 : 0;
+ vp->io_size = vortex_info_tbl[chip_idx].io_size;
/* module list only for EISA devices */
if (pdev == NULL) {
vp->next_module = root_vortex_eisa_dev;
root_vortex_eisa_dev = dev;
}
-
+
/* PCI-only startup logic */
if (pdev) {
/* EISA resources already marked, so only PCI needs to do this here */
}
/* wake up and enable device */
- if (pci_enable_device (pdev)) {
+ if ((retval = pci_enable_device(pdev))) {
printk (KERN_ERR "%s: Cannot enable device, aborting\n", dev->name);
- retval = -EIO;
goto free_region;
}
}
vp->lock = SPIN_LOCK_UNLOCKED;
- vp->chip_id = chip_idx;
vp->pdev = pdev;
/* Makes sure rings are at least 16 byte aligned. */
dev->irq);
#endif
- if (pdev && vortex_info_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+ if (pdev && vortex_info_tbl[chip_idx].drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
fn_st_addr = pci_resource_start (pdev, 2);
if (fn_st_addr)
vp->cb_fn_base = ioremap(fn_st_addr, 128);
printk(KERN_INFO "%s: CardBus functions mapped %8.8x->%p\n",
dev->name, fn_st_addr, vp->cb_fn_base);
-#if 0 /* AKPM */
- if (vortex_pci_tbl[vp->chip_id].device != 0x5257) {
+#if 1 /* AKPM: the 575_cb and 905B LEDs seem OK without this */
+ if (vortex_pci_tbl[chip_idx].device != 0x5257) {
EL3WINDOW(2);
outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
}
}
{
- static char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+ static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
union wn3_config config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
free_region:
release_region (ioaddr, vortex_info_tbl[chip_idx].io_size);
free_dev:
+ unregister_netdev(dev);
kfree (dev);
printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval);
out:
static void wait_for_completion(struct net_device *dev, int cmd)
{
- int i = 2000;
+ int i = 4000;
outw(cmd, dev->base_addr + EL3_CMD);
while (--i > 0)
media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
} else if (vp->autoselect) {
- if (vortex_info_tbl[vp->chip_id].drv_flags & HAS_NWAY) {
+ if (vp->has_nway) {
printk(KERN_INFO "%s: using NWAY autonegotiation\n", dev->name);
dev->if_port = XCVR_NWAY;
} else {
dev->if_port = XCVR_100baseTx;
while (! (vp->available_media & media_tbl[dev->if_port].mask))
dev->if_port = media_tbl[dev->if_port].next;
- printk(KERN_INFO "%s: first avaialble mdeia type: %s\n",
+ printk(KERN_INFO "%s: first available media type: %s\n",
dev->name,
media_tbl[dev->if_port].name);
}
vp->full_duplex = vp->force_fd;
config.u.xcvr = dev->if_port;
- if ( ! (vortex_info_tbl[vp->chip_id].drv_flags & HAS_NWAY))
+//AKPM if (!vp->has_nway)
{
if (vortex_debug > 6)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n",
outb(dev->dev_addr[i], ioaddr + i);
for (; i < 12; i+=2)
outw(0, ioaddr + i);
+
if (vp->cb_fn_base) {
u_short n = inw(ioaddr + Wn2_ResetOptions);
#if 0 /* AKPM: This is done in vortex_probe1, and seems to be wrong anyway... */
/* Initialize the RxEarly register as recommended. */
outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
outl(0x0020, ioaddr + PktStatus);
- outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
+ outl(vp->rx_ring_dma, ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
dev->hard_start_xmit = &boomerang_start_xmit;
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
writel(0x8000, vp->cb_fn_base + 4);
- /* AKPM: unjam the 3CCFE575CT */
- wait_for_completion(dev, TxReset);
- outw(TxEnable, ioaddr + EL3_CMD);
+ if (extra_reset)
+ {
+ /* AKPM: unjam the 3CCFE575CT */
+ wait_for_completion(dev, TxReset);
+ if (vp->full_bus_master_tx) {
+ outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+ outw(DownUnstall, ioaddr + EL3_CMD);
+ }
+ outw(TxEnable, ioaddr + EL3_CMD);
+ }
}
static int
printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name);
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
- vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
+ vp->rx_ring[i].next = cpu_to_le32(vp->rx_ring_dma + sizeof(struct boom_rx_desc) * (i+1));
vp->rx_ring[i].status = 0; /* Clear complete bit. */
vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
skb = dev_alloc_skb(PKT_BUF_SZ);
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
+ vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
}
/* Wrap the ring. */
- vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
+ vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
}
vortex_up(dev);
printk(KERN_DEBUG "%s: Media %s has link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
} else if (vortex_debug > 1)
- printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
+ printk(KERN_DEBUG "%s: Media %s has no link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
break;
case XCVR_MII: case XCVR_NWAY:
outb((vp->full_duplex ? 0x20 : 0) |
(dev->mtu > 1500 ? 0x40 : 0),
ioaddr + Wn3_MAC_Ctrl);
+ if (vortex_debug > 1)
+ printk(KERN_DEBUG "Setting duplex in Wn3_MAC_Ctrl\n");
+ /* AKPM: bug: should reset Tx and Rx after setting Duplex. Page 180 */
}
next_tick = 60*HZ;
}
outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
+ if (vortex_debug > 1)
+ printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config.i);
+ /* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */
}
EL3WINDOW(old_window);
enable_irq(dev->irq);
}
}
- if (vortex_debug > 0) {
- if (vp->full_bus_master_tx) {
- int i;
- printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d "
- "current %d.\n",
- vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx);
- printk(KERN_DEBUG " Transmit list %8.8x vs. %p.\n",
- inl(ioaddr + DownListPtr),
- &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
- for (i = 0; i < TX_RING_SIZE; i++) {
- printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i,
- &vp->tx_ring[i],
- le32_to_cpu(vp->tx_ring[i].length),
- le32_to_cpu(vp->tx_ring[i].status));
- }
- }
- }
+ if (vortex_debug > 1)
+ dump_tx_ring(dev);
wait_for_completion(dev, TxReset);
ioaddr + DownListPtr);
if (vp->tx_full && (vp->cur_tx - vp->dirty_tx <= TX_RING_SIZE - 1)) {
vp->tx_full = 0;
- netif_start_queue (dev);
+ netif_wake_queue (dev);
}
if (vp->tx_full)
netif_stop_queue (dev);
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
int do_tx_reset = 0;
+ unsigned char tx_status = 0;
- if (vortex_debug > 2)
+ if (vortex_debug > 2) {
printk(KERN_DEBUG "%s: vortex_error(), status=0x%x\n", dev->name, status);
+ }
if (status & TxComplete) { /* Really "TxError" for us. */
- unsigned char tx_status = inb(ioaddr + TxStatus);
+ tx_status = inb(ioaddr + TxStatus);
/* Presumably a tx-timeout. We must merely re-enable. */
if (vortex_debug > 2
- || (tx_status != 0x88 && vortex_debug > 0))
+ || (tx_status != 0x88 && vortex_debug > 0)) {
printk(KERN_DEBUG"%s: Transmit error, Tx status register %2.2x.\n",
dev->name, tx_status);
+ dump_tx_ring(dev);
+ }
if (tx_status & 0x14) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
outb(0, ioaddr + TxStatus);
- if (tx_status & 0x30)
+ if (tx_status & 0x38) /* AKPM: tx reset after 16 collisions, despite what the manual says */
do_tx_reset = 1;
else /* Merely re-enable the transmitter. */
outw(TxEnable, ioaddr + EL3_CMD);
}
+
if (status & RxEarly) { /* Rx early is unused. */
vortex_rx(dev);
outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
"stats as an interrupt source.\n", dev->name);
EL3WINDOW(5);
outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
+ vp->intr_enable &= ~StatsFull;
EL3WINDOW(7);
DoneDidThat++;
}
outw(AckIntr | HostError, ioaddr + EL3_CMD);
}
}
+
+ /*
+ * Black magic. If we're resetting the transmitter, remember the current downlist
+ * pointer and restore it afterwards. We can't usr cur_tx because that could
+ * lag the actual hardware index.
+ */
if (do_tx_reset) {
- wait_for_completion(dev, TxReset);
- outw(TxEnable, ioaddr + EL3_CMD);
- }
+ if (vp->full_bus_master_tx) {
+ unsigned long old_down_list_ptr;
+
+ wait_for_completion(dev, DownStall);
+ old_down_list_ptr = inl(ioaddr + DownListPtr);
+ wait_for_completion(dev, TxReset);
+ outw(TxEnable, ioaddr + EL3_CMD);
+
+ /* Restart DMA if necessary */
+ outl(old_down_list_ptr, ioaddr + DownListPtr);
+ if (vortex_debug > 2)
+ printk(KERN_DEBUG "reset DMA to 0x%08x\n", inl(ioaddr + DownListPtr));
+ outw(DownUnstall, ioaddr + EL3_CMD);
+ /*
+ * Here we make a single attempt to prevent a timeout by
+ * restarting the timer if we think that the ISR has a good
+ * chance of unjamming things.
+ */
+ if (vp->tx_reset_resume == 0 && vp->tx_full) {
+ vp->tx_reset_resume = 1;
+ dev->trans_start = jiffies;
+ }
+ } else {
+ wait_for_completion(dev, TxReset);
+ outw(TxEnable, ioaddr + EL3_CMD);
+ }
+ }
}
static int
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
- netif_stop_queue (dev);
-
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
if (vp->bus_master) {
outw(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
outw(StartDMADown, ioaddr + EL3_CMD);
- /* dev->tbusy will be cleared at the DMADone interrupt. */
+ /* netif_wake_queue() will be called at the DMADone interrupt. */
} else {
/* ... and the packet rounded to a doubleword. */
outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
dev_kfree_skb (skb);
if (inw(ioaddr + TxFree) > 1536) {
- netif_start_queue (dev);
- } else
+ netif_start_queue (dev); /* AKPM: redundant? */
+ } else {
/* Interrupt us when the FIFO has room for max-sized packet. */
+ netif_stop_queue(dev);
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ }
}
dev->trans_start = jiffies;
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr = dev->base_addr;
+ /* Calculate the next Tx descriptor entry. */
+ int entry = vp->cur_tx % TX_RING_SIZE;
+ struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
+ unsigned long flags;
if (vortex_debug > 6)
printk(KERN_DEBUG "boomerang_start_xmit()\n");
- netif_stop_queue (dev);
- {
- /* Calculate the next Tx descriptor entry. */
- int entry = vp->cur_tx % TX_RING_SIZE;
- struct boom_tx_desc *prev_entry =
- &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
- unsigned long flags;
-
- if (vortex_debug > 3)
- printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
- dev->name, vp->cur_tx);
- if (vp->tx_full) {
- if (vortex_debug > 0)
- printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
- dev->name);
- return 1;
- }
- vp->tx_skbuff[entry] = skb;
- vp->tx_ring[entry].next = 0;
- vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE));
- vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
- vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
-
- spin_lock_irqsave(&vp->lock, flags);
- /* Wait for the stall to complete. */
- wait_for_completion(dev, DownStall);
- prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
- if (inl(ioaddr + DownListPtr) == 0) {
- outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
- queued_packet++;
- }
+ if (vortex_debug > 3)
+ printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+ dev->name, vp->cur_tx);
+ if (vp->tx_full) {
+ if (vortex_debug > 0)
+ printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
+ dev->name);
+ return 1;
+ }
+ vp->tx_skbuff[entry] = skb;
+ vp->tx_ring[entry].next = 0;
+ vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->data, skb->len, PCI_DMA_TODEVICE));
+ vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+ vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
- vp->cur_tx++;
- if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
- vp->tx_full = 1;
- netif_stop_queue (dev);
- } else { /* Clear previous interrupt enable. */
+ spin_lock_irqsave(&vp->lock, flags);
+ /* Wait for the stall to complete. */
+ wait_for_completion(dev, DownStall);
+ prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
+ if (inl(ioaddr + DownListPtr) == 0) {
+ outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
+ queued_packet++;
+ }
+
+ vp->cur_tx++;
+ if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) {
+ vp->tx_full = 1;
+ netif_stop_queue (dev);
+ } else { /* Clear previous interrupt enable. */
#if defined(tx_interrupt_mitigation)
- prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
+ prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
#endif
- netif_start_queue (dev);
- }
- outw(DownUnstall, ioaddr + EL3_CMD);
- spin_unlock_irqrestore(&vp->lock, flags);
- dev->trans_start = jiffies;
- return 0;
+ /* netif_start_queue (dev); */ /* AKPM: redundant? */
}
+ outw(DownUnstall, ioaddr + EL3_CMD);
+ vp->tx_reset_resume = 0;
+ spin_unlock_irqrestore(&vp->lock, flags);
+ dev->trans_start = jiffies;
+ return 0;
}
/* The interrupt handler does all of the Rx thread work and cleans up
struct net_device *dev = dev_id;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr;
- int latency, status;
+ int status;
int work_done = max_interrupt_work;
spin_lock(&vp->lock);
ioaddr = dev->base_addr;
- latency = inb(ioaddr + Timer);
status = inw(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
- printk("AKPM: vortex_interrupt. status=0x%4x\n", status);
+ printk("vortex_interrupt(). status=0x%4x\n", status);
if (status & IntReq) {
status |= vp->deferred;
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, latency);
+ dev->name, status, inb(ioaddr + Timer));
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
pci_unmap_single(vp->pdev, vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(vp->tx_skb); /* Release the transfered buffer */
+ dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
if (inw(ioaddr + TxFree) > 1536) {
- netif_wake_queue (dev);
+ /*
+ * AKPM: FIXME: I don't think we need this. If the queue was stopped due to
+ * insufficient FIFO room, the TxAvailable test will succeed and call
+ * netif_wake_queue()
+ */
+ netif_wake_queue(dev);
} else { /* Interrupt when FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
- netif_stop_queue (dev); /* AKPM: This is new */
+ netif_stop_queue(dev); /* AKPM: This is new */
}
}
}
outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
} while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
- mod_timer(&vp->timer, jiffies+1*HZ);
+ mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
struct net_device *dev = dev_id;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
long ioaddr;
- int latency, status;
+ int status;
int work_done = max_interrupt_work;
spin_lock(&vp->lock);
ioaddr = dev->base_addr;
- latency = inb(ioaddr + Timer);
status = inw(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
- if (status & IntReq) {
- status |= vp->deferred;
- vp->deferred = 0;
- }
-
- if (status == 0xffff) /* AKPM: h/w no longer present (hotplug)? */
- {
+ if (status == 0xffff) { /* AKPM: h/w no longer present (hotplug)? */
if (vortex_debug > 1)
printk(KERN_DEBUG "boomerang_interrupt(1): status = 0xffff\n");
goto handler_exit;
}
+ if (status & IntReq) {
+ status |= vp->deferred;
+ vp->deferred = 0;
+ }
+
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, latency);
+ dev->name, status, inb(ioaddr + Timer));
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
netif_stop_queue (dev);
/* Check for all uncommon interrupts at once. */
- if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
- if (status == 0xffff)
- break;
+ if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
vortex_error(dev, status);
- }
if (--work_done < 0) {
printk(KERN_WARNING "%s: Too much work in interrupt, status "
outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
} while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
- mod_timer(&vp->timer, jiffies+1*HZ);
+ mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
if (vortex_debug > 5)
- printk(KERN_DEBUG "boomerang_rx(): status %4.4x, rx_status "
- "%4.4x.\n",
- inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
+ printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", inw(ioaddr+EL3_STATUS));
+
while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
if (--rx_work_limit < 0)
break;
return 0;
}
+static void
+dump_tx_ring(struct net_device *dev)
+{
+ if (vortex_debug > 0) {
+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+
+ if (vp->full_bus_master_tx) {
+ int i;
+ int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
+
+ wait_for_completion(dev, DownStall);
+ printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d(%d) "
+ "current %d(%d).\n",
+ vp->full_bus_master_tx, vp->tx_full,
+ vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
+ vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
+ printk(KERN_DEBUG " Transmit list %8.8x vs. %p.\n",
+ inl(ioaddr + DownListPtr),
+ &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i,
+ &vp->tx_ring[i],
+ le32_to_cpu(vp->tx_ring[i].length),
+ le32_to_cpu(vp->tx_ring[i].status));
+ }
+ if (!stalled)
+ outw(DownUnstall, ioaddr + EL3_CMD);
+ }
+ }
+}
+
static struct net_device_stats *vortex_get_stats(struct net_device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
struct net_device *dev = pdev->driver_data;
struct vortex_private *vp;
- if (!dev)
- return;
+ if (!dev) {
+ printk("vortex_remove_one called for EISA device!\n");
+ BUG();
+ }
vp = (void *)(dev->priv);
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+ /* AKPM: FIXME: we should have
+ * if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
+ * here
+ */
unregister_netdev(dev);
outw(TotalReset, dev->base_addr + EL3_CMD);
- release_region(dev->base_addr, vortex_info_tbl[vp->chip_id].io_size);
+ release_region(dev->base_addr, vp->io_size);
kfree(dev);
}
#endif
#ifdef MODULE
-static char devicename[9] =
-{0,};
static struct net_device dev_82596 =
{
- devicename, /* device name inserted by drivers/net/net_init.c */
+ "", /* device name inserted by drivers/net/net_init.c */
0, 0, 0, 0,
0, 0, /* base, irq */
0, 0, 0, NULL, i82596_probe};
#ifdef MODULE
#define MAX_AC32_CARDS 4 /* Max number of AC32 cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_AC32_CARDS] = { 0, };
static struct net_device dev_ac32[MAX_AC32_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
struct net_device *dev = &dev_ac32[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = mem[this_dev]; /* Currently ignored by driver */
}
#ifdef MODULE
-static char lt_name[16];
-
static struct net_device cops0_dev =
{
- lt_name, /* device name */
+ "", /* device name */
0, 0, 0, 0,
0x0, 0, /* I/O address, IRQ */
0, 0, 0, NULL, cops_probe
#ifdef MODULE
-static char dev_name[8];
-
static struct net_device dev_ltpc = {
- dev_name,
+ "",
0, 0, 0, 0,
0x0, 0,
0, 0, 0, NULL, ltpc_probe };
BUGMSG(D_NORMAL, "Can't allocate device data!\n");
goto err_free_irq;
}
+ lp->card_name = "RIM I";
lp->hw.command = arcrimi_command;
lp->hw.status = arcrimi_status;
lp->hw.intmask = arcrimi_setmask;
* <jojo@repas.de>
*/
-#define VERSION "arcnet: v3.92 BETA 2000/02/13 - by Avery Pennarun et al.\n"
+#define VERSION "arcnet: v3.93 BETA 2000/04/29 - by Avery Pennarun et al.\n"
#include <linux/module.h>
#include <linux/config.h>
soft = &pkt->soft.rfc1201;
proto = arc_proto_map[soft->proto];
+ BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n",
+ skb->len, pkt->hard.dest);
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
/* fits in one packet? */
{
int ioaddr;
unsigned long airqmask;
+ struct arcnet_local *lp = dev->priv;
#ifndef MODULE
arcnet_init();
}
}
}
+
+ lp->card_name = "ISA COM20020";
return com20020_found(dev, 0);
}
static char *device; /* use eg. device="arc1" to change name */
static int timeout = 3;
static int backplane = 0;
-static int clock = 0;
+static int clockp = 0;
+static int clockm = 0;
MODULE_PARM(node, "i");
MODULE_PARM(io, "i");
MODULE_PARM(device, "s");
MODULE_PARM(timeout, "i");
MODULE_PARM(backplane, "i");
-MODULE_PARM(clock, "i");
+MODULE_PARM(clockp, "i");
+MODULE_PARM(clockm, "i");
static void com20020isa_open_close(struct net_device *dev, bool open)
{
dev->dev_addr[0] = node;
lp->backplane = backplane;
- lp->clock = clock & 7;
+ lp->clockp = clockp & 7;
+ lp->clockm = clockm & 3;
lp->timeout = timeout & 3;
lp->hw.open_close_ll = com20020isa_open_close;
void cleanup_module(void)
{
- struct net_device *dev = my_dev;
-
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- kfree(dev->priv);
- kfree(dev);
+ com20020_remove(my_dev);
}
#else
#define VERSION "arcnet: COM20020 PCI support\n"
-#ifdef MODULE
-#define MAX_CARDS 16
-static struct net_device *cards[MAX_CARDS];
-static int numcards;
-#endif
+/* Module parameters */
+
+static int node = 0;
+static char *device; /* use eg. device="arc1" to change name */
+static int timeout = 3;
+static int backplane = 0;
+static int clockp = 0;
+static int clockm = 0;
+
+MODULE_PARM(node, "i");
+MODULE_PARM(device, "s");
+MODULE_PARM(timeout, "i");
+MODULE_PARM(backplane, "i");
+MODULE_PARM(clockp, "i");
+MODULE_PARM(clockm, "i");
static void com20020pci_open_close(struct net_device *dev, bool open)
{
MOD_DEC_USE_COUNT;
}
-/*
- * No need to probe for PCI cards - just ask the PCI layer and launch all the
- * ones we find.
- */
-static int __init com20020pci_probe(char *name_template, int node, int backplane, int clock, int timeout)
+static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *dev;
struct arcnet_local *lp;
- struct pci_dev *pdev = NULL;
- int ioaddr, gotone = 0, err;
-
- BUGLVL(D_NORMAL) printk(VERSION);
-
- while ((pdev = pci_find_device(0x1571, 0xa004, pdev))) {
- if (pci_enable_device(pdev))
- continue;
- dev = dev_alloc(name_template ? : "arc%d", &err);
- if (!dev)
- return err;
- lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
- if (!lp)
- return -ENOMEM;
- memset(lp, 0, sizeof(struct arcnet_local));
-
- ioaddr = pdev->resource[2].start;
- dev->base_addr = ioaddr;
- dev->irq = pdev->irq;
- dev->dev_addr[0] = node;
- lp->backplane = backplane;
- lp->clock = clock;
- lp->timeout = timeout;
- lp->hw.open_close_ll = com20020pci_open_close;
-
- BUGMSG(D_INIT, "PCI BIOS reports a device at %Xh, IRQ %d\n",
- ioaddr, dev->irq);
-
- if (check_region(ioaddr, ARCNET_TOTAL_SIZE)) {
- BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n",
- ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
- continue;
- }
- if (ASTATUS() == 0xFF) {
- BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
- "but seems empty!\n", ioaddr);
- continue;
- }
- if (com20020_check(dev))
- continue;
-
- if (!com20020_found(dev, SA_SHIRQ)) {
-#ifdef MODULE
- if(numcards==MAX_CARDS)
- printk(KERN_WARNING "com20020pci: Too many cards. Ignoring.\n");
- else
- cards[numcards++] = dev;
-#endif
- gotone++;
- }
+ int ioaddr, err;
+
+ if (pci_enable_device(pdev))
+ return -EIO;
+ dev = dev_alloc(device ? : "arc%d", &err);
+ if (!dev)
+ return err;
+ lp = dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
+ if (!lp)
+ return -ENOMEM;
+ memset(lp, 0, sizeof(struct arcnet_local));
+ pdev->driver_data = dev;
+
+ ioaddr = pci_resource_start(pdev, 2);
+ dev->base_addr = ioaddr;
+ dev->irq = pdev->irq;
+ dev->dev_addr[0] = node;
+ lp->card_name = pdev->name;
+ lp->card_flags = id->driver_data;
+ lp->backplane = backplane;
+ lp->clockp = clockp & 7;
+ lp->clockm = clockm & 3;
+ lp->timeout = timeout;
+ lp->hw.open_close_ll = com20020pci_open_close;
+
+ if (check_region(ioaddr, ARCNET_TOTAL_SIZE)) {
+ BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n",
+ ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
+ return -EBUSY;
+ }
+ if (ASTATUS() == 0xFF) {
+ BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, "
+ "but seems empty!\n", ioaddr);
+ return -EIO;
}
+ if (com20020_check(dev))
+ return -EIO;
- return gotone ? 0 : -ENODEV;
+ return com20020_found(dev, SA_SHIRQ);
}
-
-#ifdef MODULE
-
-/* Module parameters */
-
-static int node = 0;
-static char *device; /* use eg. device="arc1" to change name */
-static int timeout = 3;
-static int backplane = 0;
-static int clock = 0;
-
-MODULE_PARM(node, "i");
-MODULE_PARM(device, "s");
-MODULE_PARM(timeout, "i");
-MODULE_PARM(backplane, "i");
-MODULE_PARM(clock, "i");
-
-int init_module(void)
+static void __devexit com20020pci_remove(struct pci_dev *pdev)
{
- return com20020pci_probe(device, node, backplane, clock & 7, timeout & 3);
+ com20020_remove(pdev->driver_data);
}
-void cleanup_module(void)
+static struct pci_device_id com20020pci_id_table[] __devinitdata = {
+ { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1571, 0xa009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa00a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT },
+ { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT },
+ {0,}
+};
+
+static struct pci_driver com20020pci_driver __devinitdata = {
+ name: "com20020",
+ id_table: com20020pci_id_table,
+ probe: com20020pci_probe,
+ remove: com20020pci_remove
+};
+
+int com20020pci_init(void)
{
- struct net_device *dev;
- int count;
-
- for (count = 0; count < numcards; count++) {
- dev = cards[count];
- unregister_netdev(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
- kfree(dev->priv);
- kfree(dev);
- }
+ BUGLVL(D_NORMAL) printk(VERSION);
+#ifndef MODULE
+ arcnet_init();
+#endif
+ return pci_module_init(&com20020pci_driver);
}
-#else
-
-void __init com20020pci_probe_all(void)
+void com20020pci_cleanup(void)
{
- com20020pci_probe(NULL, 0, 0, 0, 3);
+ pci_unregister_driver(&com20020pci_driver);
}
-#endif /* MODULE */
+module_init(com20020pci_init)
+module_exit(com20020pci_cleanup)
#define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n"
static char *clockrates[] =
-{"2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s",
- "156.25 Kb/s", "Reserved", "Reserved",
- "Reserved"};
+{"10 Mb/s", "Reserved", "5 Mb/s",
+ "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s",
+ "156.25 Kb/s", "Reserved", "Reserved", "Reserved"};
static void com20020_command(struct net_device *dev, int command);
static int com20020_status(struct net_device *dev);
/* Reset the card and check some basic stuff during the detection stage. */
-int __init com20020_check(struct net_device *dev)
+int __devinit com20020_check(struct net_device *dev)
{
int ioaddr = dev->base_addr, status;
struct arcnet_local *lp = dev->priv;
ARCRESET0;
mdelay(RESETtime);
- lp->setup = lp->clock << 1;
+ lp->setup = lp->clockm ? 0 : (lp->clockp << 1);
+ lp->setup2 = (lp->clockm << 4) | 8;
- REGSETUP;
- SETCONF(lp->config);
- outb(lp->setup, ioaddr + 7);
+ SET_SUBADR(SUB_SETUP1);
+ outb(lp->setup, _XREG);
+
+ if (lp->card_flags & ARC_CAN_10MBIT)
+ {
+ SET_SUBADR(SUB_SETUP2);
+ outb(lp->setup2, _XREG);
+
+ /* must now write the magic "restart operation" command */
+ mdelay(1);
+ outb(0x18, _COMMAND);
+ }
lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2);
/* set node ID to 0x42 (but transmitter is disabled, so it's okay) */
- SETCONF(lp->config);
+ SETCONF;
outb(0x42, ioaddr + 7);
status = ASTATUS();
/* Set up the struct net_device associated with this card. Called after
* probing succeeds.
*/
-int __init com20020_found(struct net_device *dev, int shared)
+int __devinit com20020_found(struct net_device *dev, int shared)
{
struct arcnet_local *lp;
int ioaddr = dev->base_addr;
if (!dev->dev_addr[0])
dev->dev_addr[0] = inb(ioaddr + 8); /* FIXME: do this some other way! */
- lp->setup = lp->clock << 1;
+ SET_SUBADR(SUB_SETUP1);
+ outb(lp->setup, _XREG);
+
+ if (lp->card_flags & ARC_CAN_10MBIT)
+ {
+ SET_SUBADR(SUB_SETUP2);
+ outb(lp->setup2, _XREG);
+
+ /* must now write the magic "restart operation" command */
+ mdelay(1);
+ outb(0x18, _COMMAND);
+ }
- REGSETUP;
- SETCONF(lp->config);
- outb(lp->setup, ioaddr + 7);
lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1;
/* Default 0x38 + register: Node ID */
- SETCONF(lp->config);
- outb(dev->dev_addr[0], ioaddr + 7);
+ SETCONF;
+ outb(dev->dev_addr[0], _XREG);
/* reserve the irq */
if (request_irq(dev->irq, &arcnet_interrupt, shared,
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
- /* reserve the I/O region - guaranteed to work by check_region */
- request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)");
+ /* reserve the I/O region */
+ if (request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) {
+ free_irq(dev->irq, dev);
+ return -EBUSY;
+ }
dev->base_addr = ioaddr;
- BUGMSG(D_NORMAL, "COM20020: station %02Xh found at %03lXh, IRQ %d.\n",
- dev->dev_addr[0], dev->base_addr, dev->irq);
+ BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
+ lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
if (lp->backplane)
BUGMSG(D_NORMAL, "Using backplane mode.\n");
if (lp->timeout != 3)
BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout);
- if (lp->setup) {
- BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
- lp->setup >> 1, clockrates[lp->setup >> 1]);
- }
+
+ BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n",
+ lp->setup >> 1,
+ clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]);
+
if (!dev->init && register_netdev(dev)) {
free_irq(dev->irq, dev);
release_region(ioaddr, ARCNET_TOTAL_SIZE);
lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2);
/* power-up defaults */
- SETCONF(lp->config);
+ SETCONF;
if (really_reset) {
/* reset the card */
else {
/* disable transmitter */
lp->config &= ~TXENcfg;
- SETCONF(lp->config);
+ SETCONF;
MOD_DEC_USE_COUNT;
}
lp->hw.open_close_ll(dev, open);
if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */
if (!(lp->setup & PROMISCset))
BUGMSG(D_NORMAL, "Setting promiscuous flag...\n");
- REGSETUP;
- SETCONF(lp->config);
+ SET_SUBADR(SUB_SETUP1);
lp->setup |= PROMISCset;
- outb(lp->setup, _SETUP);
+ outb(lp->setup, _XREG);
} else
/* Disable promiscuous mode, use normal mode */
{
if ((lp->setup & PROMISCset))
BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n");
- REGSETUP;
- SETCONF(lp->config);
+ SET_SUBADR(SUB_SETUP1);
lp->setup &= ~PROMISCset;
- outb(lp->setup, _SETUP);
+ outb(lp->setup, _XREG);
}
}
-
-/*
- * FIXME: put this somewhere!
- *
- if ((dstatus = inb(_DIAGSTAT)) & NEWNXTIDflag)
- {
- REGNXTID;
- SETCONF(lp->config);
- BUGMSG(D_EXTRA, "New NextID detected: %X\n", inb(ioaddr + 7));
- }
- */
-
+void __devexit com20020_remove(struct net_device *dev)
+{
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
+ kfree(dev->priv);
+ kfree(dev);
+}
#ifdef MODULE
EXPORT_SYMBOL(com20020_check);
EXPORT_SYMBOL(com20020_found);
+EXPORT_SYMBOL(com20020_remove);
int init_module(void)
{
memset(dev->priv, 0, sizeof(struct arcnet_local));
lp = (struct arcnet_local *) (dev->priv);
+ lp->card_name = "COM90xx I/O";
lp->hw.command = com90io_command;
lp->hw.status = com90io_status;
lp->hw.intmask = com90io_setmask;
/* Initialize the rest of the device structure. */
memset(lp, 0, sizeof(struct arcnet_local));
+ lp->card_name = "COM90xx";
lp->hw.command = com90xx_command;
lp->hw.status = com90xx_status;
lp->hw.intmask = com90xx_setmask;
if (in->numpackets > 16) {
BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
soft->split_flag);
+ lp->rfc1201.aborted_seq = soft->sequence;
lp->stats.rx_errors++;
lp->stats.rx_length_errors++;
return;
GFP_ATOMIC);
if (skb == NULL) {
BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
+ lp->rfc1201.aborted_seq = soft->sequence;
lp->stats.rx_dropped++;
return;
}
in->skb = NULL;
in->lastpacket = in->numpackets = 0;
+ BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n",
+ skb->len, pkt->hard.source);
+ BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n",
+ skb->len, pkt->hard.source);
BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
skb->protocol = type_trans(skb, dev);
hard->offset[0] = 0;
hard->offset[1] = ofs = 512 - softlen;
} else if (softlen > MTU) { /* exception packet - add an extra header */
- struct arc_rfc1201 excsoft =
- {soft->proto, 0xFF, 0xFFFF};
+ struct arc_rfc1201 excsoft;
+
+ excsoft.proto = soft->proto;
+ excsoft.split_flag = 0xff;
+ excsoft.sequence = 0xffff;
hard->offset[0] = 0;
ofs = 512 - softlen;
}
#ifdef MODULE
-static char devicename[9] = { 0, };
static struct net_device dev_at1700 = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+ "", /* device name is inserted by linux/drivers/net/net_init.c */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, at1700_probe };
#ifdef MODULE
static int io = 0;
-static char nullname[8] = "";
static struct net_device atp_dev = {
- nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, atp_probe };
+ "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, atp_probe };
MODULE_PARM(io, "I/O port of the pocket adapter");
#ifdef MODULE
-static char bond_name[16];
-
static struct net_device dev_bond = {
- bond_name, /* Needs to be writeable */
+ "",
0, 0, 0, 0,
0x0, 0,
0, 0, 0, NULL, bond_init };
#ifdef MODULE
-static char namespace[16] = "";
static struct net_device dev_cs89x0 = {
- NULL,
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL };
#if DEBUGGING
net_debug = debug;
#endif
- dev_cs89x0.name = namespace;
dev_cs89x0.irq = irq;
dev_cs89x0.base_addr = io;
{
struct net_device *new;
- new = (struct net_device *)kmalloc(sizeof(struct net_device)+8, GFP_KERNEL);
+ new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (new == NULL) {
printk("de4x5.c: Device not initialised, insufficient memory\n");
return NULL;
} else {
- memset((char *)new, 0, sizeof(struct net_device)+8);
- new->name = (char *)(new + 1);
+ memset((char *)new, 0, sizeof(struct net_device));
new->base_addr = iobase; /* assign the io address */
new->init = init; /* initialisation routine */
}
#endif
\f
#ifdef MODULE
-static char nullname[8];
static struct net_device de600_dev = {
- nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
+ "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe };
int
init_module(void)
*
*/
#ifdef MODULE
-static char nullname[8] = "";
static struct net_device de620_dev = {
- nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe };
+ "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe };
int init_module(void)
{
{
struct net_device *new;
- new = (struct net_device *)kmalloc(sizeof(struct net_device)+8, GFP_KERNEL);
+ new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (new == NULL) {
printk("eth%d: Device not initialised, insufficient memory\n",num_eth);
return NULL;
new->next = dev->next;
dev->next = new;
dev = dev->next; /* point to the new device */
- dev->name = (char *)(dev + 1);
if (num_eth > 9999) {
sprintf(dev->name,"eth????");/* New device name */
} else {
}
#ifdef MODULE
-static char devicename[9] = {0,};
static struct net_device thisDepca = {
- devicename, /* device name is inserted by /linux/drivers/net/net_init.c */
+ "", /* device name is inserted by /linux/drivers/net/net_init.c */
0, 0, 0, 0,
0x200, 7, /* I/O address, IRQ */
0, 0, 0, NULL, depca_probe
/*
* Stuff for generic ethercard I/F
*/
- char devname[8]; /* "ethN" string */
struct net_device *next_dev;
struct net_device_stats stats;
dev->priv = ((void *)dev) + sizeof(struct net_device);
priv = (DGRS_PRIV *)dev->priv;
- dev->name = priv->devname; /* An empty string. */
dev->base_addr = io;
dev->mem_start = mem;
dev->mem_end = mem + 2048 * 1024 - 1;
memcpy(devN, dev, dev_size);
devN->priv = ((void *)devN) + sizeof(struct net_device);
privN = (DGRS_PRIV *)devN->priv;
- /* ... but seset devname to a NULL string */
- privN->devname[0] = 0;
- devN->name = privN->devname;
/* ... and zero out VM areas */
privN->vmem = 0;
privN->vplxdma = 0;
return 0;
}
-static char dummy_name[16];
-
static struct net_device dev_dummy = {
- dummy_name, /* Needs to be writeable */
+ "",
0, 0, 0, 0,
0x0, 0,
0, 0, 0, NULL, dummy_probe };
\f
#ifdef MODULE
#define MAX_E21_CARDS 4 /* Max number of E21 cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_E21_CARDS] = { 0, };
static struct net_device dev_e21[MAX_E21_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
struct net_device *dev = &dev_e21[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = mem[this_dev];
}
#define MAX_EEPRO 8
-static char devicename[MAX_EEPRO][9];
static struct net_device dev_eepro[MAX_EEPRO];
static int io[MAX_EEPRO] = {
while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
struct net_device *d = &dev_eepro[n_eepro];
- d->name = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
d->mem_end = mem[n_eepro];
d->base_addr = io[n_eepro];
d->irq = irq[n_eepro];
#ifdef MODULE
#define EEXP_MAX_CARDS 4 /* max number of cards to support */
-#define NAMELEN 8 /* max length of dev->name (inc null) */
-
-static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, };
static struct net_device dev_eexp[EEXP_MAX_CARDS] =
{
- { NULL, /* will allocate dynamically */
+ { "",
0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe },
};
for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_eexp[this_dev];
- dev->name = namelist + (NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
if (io[this_dev] == 0) {
}
#define MAX_ETH16I_CARDS 4 /* Max number of Eth16i cards per module */
-#define NAMELEN 8 /* number of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_ETH16I_CARDS] = { 0, };
static struct net_device dev_eth16i[MAX_ETH16I_CARDS] = {
{
- NULL,
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
{
struct net_device *dev = &dev_eth16i[this_dev];
- dev->name = namelist + (NAMELEN*this_dev);
dev->irq = 0; /* irq[this_dev]; */
dev->base_addr = io[this_dev];
dev->init = eth16i_probe;
\f
#ifdef MODULE
#define MAX_HPP_CARDS 4 /* Max number of HPP cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_HPP_CARDS] = { 0, };
static struct net_device dev_hpp[MAX_HPP_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
struct net_device *dev = &dev_hpp[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = hp_plus_probe;
#ifdef MODULE
#define MAX_HP_CARDS 4 /* Max number of HP cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_HP_CARDS] = { 0, };
static struct net_device dev_hp[MAX_HP_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
struct net_device *dev = &dev_hp[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = hp_probe;
MODULE_PARM(hp100_port, "1-5i");
#endif
-#ifdef LINUX_2_1
-char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" };
-MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ));
-#else
+#ifndef LINUX_2_1
static char devname[5][IFNAMSIZ] = { "", "", "", "", "" };
static char *hp100_name[5] = { devname[0], devname[1],
devname[2], devname[3],
/* Create device and set basics args */
hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL);
memset(hp100_devlist[i], 0x00, sizeof(struct net_device));
+#ifndef LINUX_2_1
hp100_devlist[i]->name = hp100_name[i];
+#endif
hp100_devlist[i]->base_addr = hp100_port[i];
hp100_devlist[i]->init = &hp100_probe;
#ifdef MODULE
#define MAX_CARDS 8 /* Max number of interfaces (cards) per module */
-#define IF_NAMELEN 8 /* # of chars for storing dev->name */
static int io[MAX_CARDS] = { 0, };
static int dma[MAX_CARDS] = { 0, };
MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
-static char ifnames[MAX_CARDS][IF_NAMELEN] = { {0, }, };
static struct net_device dev_lance[MAX_CARDS] =
{{
- 0, /* device name is inserted by linux/drivers/net/net_init.c */
+ "", /* device name is inserted by linux/drivers/net/net_init.c */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL}};
for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
struct net_device *dev = &dev_lance[this_dev];
- dev->name = ifnames[this_dev];
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->dma = dma[this_dev];
#ifdef MODULE
#define MAX_LNE_CARDS 4 /* Max number of LNE390 cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_LNE_CARDS] = { 0, };
static struct net_device dev_lne[MAX_LNE_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
struct net_device *dev = &dev_lne[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = mem[this_dev];
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, };
static struct net_device dev_ne[MAX_NE_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
#ifdef MODULE
#define MAX_NE_CARDS 4 /* Max number of NE cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_NE_CARDS] = { 0, };
static struct net_device dev_ne[MAX_NE_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
struct net_device *dev = &dev_ne[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->mem_end = bad[this_dev];
dev->base_addr = io[this_dev];
#ifdef MODULE
#define MAX_NE3210_CARDS 4 /* Max number of NE3210 cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_NE3210_CARDS] = { 0, };
static struct net_device dev_ne3210[MAX_NE3210_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) {
struct net_device *dev = &dev_ne3210[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = mem[this_dev];
int alloc_size;
/* ensure 32-byte alignment of the private area */
- alloc_size = sizeof (*dev) + IFNAMSIZ + sizeof_priv + 31;
+ alloc_size = sizeof (*dev) + sizeof_priv + 31;
dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL);
if (dev == NULL)
if (sizeof_priv)
dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
- dev->name = sizeof_priv + 31 + (char *)(dev + 1);
return dev;
}
}
#ifdef MODULE
-static char devicename[9] = { 0, };
static struct net_device dev_ni5010 = {
- devicename,
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, ni5010_probe };
}
#ifdef MODULE
-static char devicename[9] = { 0, };
static struct net_device dev_ni52 = {
- devicename, /* "ni5210": device name inserted by net_init.c */
+ "", /* device name inserted by net_init.c */
0, 0, 0, 0,
0x300, 9, /* I/O address, IRQ */
0, 0, 0, NULL, ni52_probe };
}
#ifdef MODULE
-static char devicename[9] = { 0, };
-
static struct net_device dev_ni65 = {
- devicename, /* "ni6510": device name inserted by net_init.c */
+ "", /* "ni6510": device name inserted by net_init.c */
0, 0, 0, 0,
0x360, 9, /* I/O address, IRQ */
0, 0, 0, NULL, ni65_probe };
dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA
if [ "$CONFIG_CARDBUS" = "y" ]; then
- comment ' 3Com 3c575 moved to Ethernet 10/100 menu'
tristate ' Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP
fi
static int node = 0;
static int timeout = 3;
static int backplane = 0;
-static int clock = 0;
+static int clockp = 0;
+static int clockm = 0;
MODULE_PARM(node, "i");
MODULE_PARM(timeout, "i");
MODULE_PARM(backplane, "i");
-MODULE_PARM(clock, "i");
+MODULE_PARM(clockp, "i");
+MODULE_PARM(clockm, "i");
/* Bit map of interrupts to choose from */
static u_int irq_mask = 0xdeb8;
dev->dev_addr[0] = node;
lp->timeout = timeout;
lp->backplane = backplane;
- lp->clock = clock;
+ lp->clockp = clockp;
+ lp->clockm = clockm & 3;
lp->hw.open_close_ll = com20020cs_open_close;
link->irq.Instance = info->dev = dev;
static void com20020_config(dev_link_t *link)
{
+ struct arcnet_local *lp;
client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
}
MOD_INC_USE_COUNT;
+
+ lp = dev->priv;
+ lp->card_name = "PCMCIA COM20020";
+ lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
+
i = com20020_found(dev, 0);
if (i != 0) {
link->conf.IntType = INT_MEMORY_AND_IO;
ethdev_init(dev);
- dev->name = info->node.dev_name;
+ strcpy(dev->name, info->node.dev_name);
dev->init = &pcnet_init;
dev->open = &pcnet_open;
dev->stop = &pcnet_close;
DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n");
ether_setup(dev);
- dev->name = local->node.dev_name;
+ strcpy(dev->name, local->node.dev_name);
dev->init = &ray_dev_init;
dev->open = &ray_open;
dev->stop = &ray_dev_close;
break;
}
memset(dev_plip[i], 0, sizeof(struct net_device));
- dev_plip[i]->name =
- kmalloc(strlen("plipXXX"), GFP_KERNEL);
- if (!dev_plip[i]->name) {
- printk(KERN_ERR "plip: memory squeeze.\n");
- kfree(dev_plip[i]);
- dev_plip[i] = NULL;
- break;
- }
sprintf(dev_plip[i]->name, "plip%d", i);
dev_plip[i]->priv = pb;
if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) {
*/
struct ppp {
struct ppp_file file; /* stuff for read/write/poll */
- char name[16]; /* unit name */
struct list_head channels; /* list of attached channels */
int n_channels; /* how many channels are attached */
spinlock_t rlock; /* lock for receive side */
memset(dev, 0, sizeof(struct net_device));
ppp->file.index = unit;
- sprintf(ppp->name, "ppp%d", unit);
ppp->mru = PPP_MRU;
init_ppp_file(&ppp->file, INTERFACE);
for (i = 0; i < NUM_NP; ++i)
ppp->dev = dev;
dev->init = ppp_net_init;
- dev->name = ppp->name;
+ sprintf(dev->name, "ppp%d", unit);
dev->priv = ppp;
dev->new_style = 1;
*/
struct net_device *dev;
- char devname[8]; /* "ethN" string */
U8 id; /* the AdapterID */
U32 pci_addr; /* the pci address of the adapter */
U32 bus;
#endif
pDpa = dev->priv;
- if (!dev->name)
- dev->name = pDpa->devname;
pDpa->dev = dev; /* this is just for easy reference */
pDpa->function = function;
MODULE_PARM(io, "1-2i");
MODULE_PARM(irq, "i");
-static char devname[8] = {0, };
static struct net_device dev_sb1000 = {
- devname,
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, sb1000_probe };
{
int i;
for (i = 0; i < 100; i++) {
- sprintf(devname, "cm%d", i);
- if (dev_get(devname) == 0) break;
+ sprintf(dev_sb1000.name, "cm%d", i);
+ if (dev_get(dev_sb1000.name) == 0) break;
}
if (i == 100) {
printk(KERN_ERR "sb1000: can't register any device cm<n>\n");
#ifdef MODULE
-static char devicename[9];
-
static struct net_device dev_shape =
{
- devicename,
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, shaper_probe
#define DEVMAX 5
-static char NameSpace[8 * DEVMAX];
static struct net_device moddevs[DEVMAX] =
- { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
-{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
+ { {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe},
+{"", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, skmca_probe}
};
int irq = 0;
int len;
PRINTK(KERN_INFO "entering insert_device\n");
- len = sizeof(struct net_device) + 8 + sizeof(struct s_smc);
+ len = sizeof(struct net_device) + sizeof(struct s_smc);
new = (struct net_device *) kmalloc(len, GFP_KERNEL);
if (new == NULL) {
printk("fddi%d: Device not initialised, insufficient memory\n",
return NULL;
} else {
memset((char *) new, 0, len);
- new->name = (char *) (new + 1);
- new->priv = (struct s_smc *) (new->name + 8);
+ new->priv = (struct s_smc *) (new + 1);
new->init = init; /* initialisation routine */
if (!loading_module) {
new->next = dev->next;
typedef struct slip_ctrl {
- char if_name[16]; /* "sl0\0" .. "sl99999\0" */
struct slip ctrl; /* SLIP things */
struct net_device dev; /* the device */
} slip_ctrl_t;
sl->dev = &slp->dev;
spin_lock_init(&sl->lock);
sl->mode = SL_MODE_DEFAULT;
- sprintf(slp->if_name, "sl%d", i);
- slp->dev.name = slp->if_name;
+ sprintf(slp->dev.name, "sl%d", i);
slp->dev.base_addr = i;
slp->dev.priv = (void*)sl;
slp->dev.init = sl_init;
#undef MODULE /* don't want to bother now! */
#define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-
-static char namelist[NAMELEN * MAX_ULTRAMCA_CARDS] = { 0, };
static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS] =
{
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) {
struct net_device *dev = &dev_ultra[this_dev];
- dev->name = namelist + (NAMELEN * this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = ultramca_probe;
\f
#ifdef MODULE
#define MAX_ULTRA_CARDS 4 /* Max number of Ultra cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_ULTRA_CARDS] = { 0, };
static struct net_device dev_ultra[MAX_ULTRA_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "", /* assign a chunk of namelist[] below */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
struct net_device *dev = &dev_ultra[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->init = ultra_probe;
\f
#ifdef MODULE
#define MAX_ULTRA32_CARDS 4 /* Max number of Ultra cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_ULTRA32_CARDS] = { 0, };
static struct net_device dev_ultra[MAX_ULTRA32_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "",
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
struct net_device *dev = &dev_ultra[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->init = ultra32_probe;
if (register_netdev(dev) != 0) {
if (found > 0) { /* Got at least one. */
*/
struct tty_struct *tty; /* ptr to TTY structure */
- char8 if_name; /* Dynamically generated name */
struct net_device dev; /* Our device structure */
/*
FirmwareVersion firmware_version = strip_info->firmware_version;
SerialNumber serial_number = strip_info->serial_number;
BatteryVoltage battery_voltage = strip_info->battery_voltage;
- char8 if_name = strip_info->if_name;
+ char* if_name = strip_info->dev.name;
MetricomAddress true_dev_addr = strip_info->true_dev_addr;
MetricomAddress dev_dev_addr = *(MetricomAddress*)strip_info->dev.dev_addr;
int manual_dev_addr = strip_info->manual_dev_addr;
#endif
RestoreInterrupts(intstat);
- p += sprintf(p, "\nInterface name\t\t%s\n", if_name.c);
+ p += sprintf(p, "\nInterface name\t\t%s\n", if_name);
p += sprintf(p, " Radio working:\t\t%s\n", working ? "Yes" : "No");
radio_address_to_string(&true_dev_addr, &addr_string);
p += sprintf(p, " Radio address:\t\t%s\n", addr_string.c);
strip_info->idle_timer.function = strip_IdleTask;
/* Note: strip_info->if_name is currently 8 characters long */
- sprintf(strip_info->if_name.c, "st%d", channel_id);
- strip_info->dev.name = strip_info->if_name.c;
+ sprintf(strip_info->dev.name, "st%d", channel_id);
strip_info->dev.base_addr = channel_id;
strip_info->dev.priv = (void*)strip_info;
strip_info->dev.next = NULL;
MOD_INC_USE_COUNT;
#endif
- printk(KERN_INFO "STRIP: device \"%s\" activated\n", strip_info->if_name.c);
+ printk(KERN_INFO "STRIP: device \"%s\" activated\n", strip_info->dev.name);
/*
* Done. We have linked the TTY line to a channel.
tty->disc_data = 0;
strip_info->tty = NULL;
- printk(KERN_INFO "STRIP: device \"%s\" closed down\n", strip_info->if_name.c);
+ printk(KERN_INFO "STRIP: device \"%s\" closed down\n", strip_info->dev.name);
strip_free(strip_info);
tty->disc_data = NULL;
#ifdef MODULE
netif_device_detach (dev);
tulip_down (dev);
}
- pci_set_power_state(pdev, 3);
+// pci_set_power_state(pdev, 3);
}
-static void tulip_resume (struct pci_dev *pdev)
+static void tulip_resume(struct pci_dev *pdev)
{
struct net_device *dev = pdev->driver_data;
return -ENOMEM;
}
memset(dev, 0, sizeof(struct net_device));
- dev->name = (char *)new_dir->name;
+ strcpy(dev->name, (char *)new_dir->name);
dev->init = comx_init_dev;
if (register_netdevice(dev)) {
memset(chan->pppdev.dev, 0, sizeof(struct net_device));
sppp_attach(&chan->pppdev);
d=chan->pppdev.dev;
- d->name = chan->name;
+ strcpy(d->name, chan->name);
d->base_addr = chan->cosa->datareg;
d->irq = chan->cosa->irq;
d->dma = chan->cosa->dma;
return(-ENOMEM);
memset(master, 0, sizeof(*master));
- master->name = kmalloc(strlen(buf) + 1, GFP_KERNEL);
-
- if (!master->name)
- {
- kfree(master);
- return(-ENOMEM);
- }
strcpy(master->name, buf);
master->init = dlci_init;
err = register_netdev(master);
if (err < 0)
{
- kfree(master->name);
kfree(master);
return(err);
}
{
unregister_netdev(master);
kfree(master->priv);
- kfree(master->name);
kfree(master);
return(err);
}
open_dev[i] = NULL;
kfree(master->priv);
- kfree(master->name);
kfree(master);
MOD_DEC_USE_COUNT;
void *if_ptr; /* General purpose pointer (used by SPPP) */
struct z8530_dev sync;
struct ppp_device netdev;
- char name[16];
};
/*
dev->chanA.netdevice=sv->netdev.dev;
dev->chanA.dev=dev;
dev->chanB.dev=dev;
- dev->name=sv->name;
if(dma)
{
/*
* Now we can take the IRQ
*/
-
- for(i=0;i<999;i++)
+ if(dev_alloc_name(dev->chanA.netdevice,"hdlc%d")>=0)
{
- sprintf(sv->name,"hdlc%d", i);
- if(dev_get(sv->name)==0)
- {
- struct net_device *d=dev->chanA.netdevice;
-
- /*
- * Initialise the PPP components
- */
- sppp_attach(&sv->netdev);
-
- /*
- * Local fields
- */
- sprintf(sv->name,"hdlc%d", i);
-
- d->name = sv->name;
- d->base_addr = iobase;
- d->irq = irq;
- d->priv = sv;
- d->init = NULL;
-
- d->open = hostess_open;
- d->stop = hostess_close;
- d->hard_start_xmit = hostess_queue_xmit;
- d->get_stats = hostess_get_stats;
- d->set_multicast_list = NULL;
- d->do_ioctl = hostess_ioctl;
+ struct net_device *d=dev->chanA.netdevice;
+
+ /*
+ * Initialise the PPP components
+ */
+ sppp_attach(&sv->netdev);
+
+ /*
+ * Local fields
+ */
+
+ d->base_addr = iobase;
+ d->irq = irq;
+ d->priv = sv;
+ d->init = NULL;
+
+ d->open = hostess_open;
+ d->stop = hostess_close;
+ d->hard_start_xmit = hostess_queue_xmit;
+ d->get_stats = hostess_get_stats;
+ d->set_multicast_list = NULL;
+ d->do_ioctl = hostess_ioctl;
#ifdef LINUX_21
- d->neigh_setup = hostess_neigh_setup_dev;
- dev_init_buffers(d);
+ d->neigh_setup = hostess_neigh_setup_dev;
+ dev_init_buffers(d);
#else
- d->init = return_0;
+ d->init = return_0;
#endif
- d->set_mac_address = NULL;
-
- if(register_netdev(d)==-1)
- {
- printk(KERN_ERR "%s: unable to register device.\n",
- sv->name);
- goto fail;
- }
-
- z8530_describe(dev, "I/O", iobase);
- dev->active=1;
- return sv;
- }
+ d->set_mac_address = NULL;
+
+ if(register_netdev(d)==-1)
+ {
+ printk(KERN_ERR "%s: unable to register device.\n",
+ d->name);
+ goto fail;
+ }
+
+ z8530_describe(dev, "I/O", iobase);
+ dev->active=1;
+ return sv;
}
dmafail2:
if(dma==1)
void *if_ptr; /* General purpose pointer (used by SPPP) */
struct z8530_channel *chan;
struct ppp_device netdev;
- char name[16];
int channel;
};
struct slvl_device *sv;
struct slvl_board *b;
- int i;
unsigned long flags;
int u;
dev->chanB.netdevice=b->dev[1].netdev.dev;
dev->chanA.dev=dev;
dev->chanB.dev=dev;
- dev->name=b->dev[0].name;
dev->chanA.txdma=3;
dev->chanA.rxdma=1;
sv=&b->dev[u];
sv->channel = u;
- for(i=0;i<999;i++)
+ if(dev_alloc_name(sv->chan->netdevice,"hdlc%d")>=0)
{
- sprintf(sv->name,"hdlc%d", i);
- if(dev_get(sv->name)==0)
- {
- struct net_device *d=sv->chan->netdevice;
-
- /*
- * Initialise the PPP components
- */
- sppp_attach(&sv->netdev);
-
- /*
- * Local fields
- */
- sprintf(sv->name,"hdlc%d", i);
-
- d->name = sv->name;
- d->base_addr = iobase;
- d->irq = irq;
- d->priv = sv;
- d->init = NULL;
+ struct net_device *d=sv->chan->netdevice;
+
+ /*
+ * Initialise the PPP components
+ */
+ sppp_attach(&sv->netdev);
+
+ /*
+ * Local fields
+ */
- d->open = sealevel_open;
- d->stop = sealevel_close;
- d->hard_start_xmit = sealevel_queue_xmit;
- d->get_stats = sealevel_get_stats;
- d->set_multicast_list = NULL;
- d->do_ioctl = sealevel_ioctl;
+ d->base_addr = iobase;
+ d->irq = irq;
+ d->priv = sv;
+ d->init = NULL;
+
+ d->open = sealevel_open;
+ d->stop = sealevel_close;
+ d->hard_start_xmit = sealevel_queue_xmit;
+ d->get_stats = sealevel_get_stats;
+ d->set_multicast_list = NULL;
+ d->do_ioctl = sealevel_ioctl;
#ifdef LINUX_21
- d->neigh_setup = sealevel_neigh_setup_dev;
- dev_init_buffers(d);
+ d->neigh_setup = sealevel_neigh_setup_dev;
+ dev_init_buffers(d);
#else
- d->init = return_0;
+ d->init = return_0;
#endif
- d->set_mac_address = NULL;
-
- if(register_netdev(d)==-1)
- {
- printk(KERN_ERR "%s: unable to register device.\n",
- sv->name);
- goto fail_unit;
- }
+ d->set_mac_address = NULL;
+
+ if(register_netdev(d)==-1)
+ {
+ printk(KERN_ERR "%s: unable to register device.\n",
+ d->name);
+ goto fail_unit;
+ }
- break;
- }
+ break;
}
}
z8530_describe(dev, "I/O", iobase);
break;
}
memset(dev, 0x00, sizeof(struct net_device));
- dev->name = name[i];
dev->base_addr = io[i];
dev->irq = irq[i];
dev->init = &wavelan_config;
\f
#ifdef MODULE
#define MAX_WD_CARDS 4 /* Max number of wd cards per module */
-#define NAMELEN 8 /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_WD_CARDS] = { 0, };
static struct net_device dev_wd[MAX_WD_CARDS] = {
{
- NULL, /* assign a chunk of namelist[] below */
+ "", /* assign a chunk of namelist[] below */
0, 0, 0, 0,
0, 0,
0, 0, 0, NULL, NULL
for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
struct net_device *dev = &dev_wd[this_dev];
- dev->name = namelist+(NAMELEN*this_dev);
dev->irq = irq[this_dev];
dev->base_addr = io[this_dev];
dev->mem_start = mem[this_dev];
# Maintained by Martin Mares <pci-ids@ucw.cz>
# If you have any new entries, send them to the maintainer.
#
-# $Id: pci.ids,v 1.56 2000/04/17 16:11:58 mj Exp $
+# $Id: pci.ids,v 1.60 2000/05/01 19:53:05 mj Exp $
#
# Vendors, devices and subsystems. Please keep sorted.
0046 DECchip 21554
9005 1364 Dell PowerEdge RAID Controller 2
9005 1365 Dell PowerEdge RAID Controller 2
- 1065 RAID Controller
+ 1065 StrongARM DC21285
+ 1069 0020 DAC960P
1012 Micronics Computers Inc
1013 Cirrus Logic
0038 GD 7548
002d Python
002e ServeRAID controller
0036 Miami
+ 003a CPU to PCI Bridge
003e 16/4 Token ring UTP/STP controller
1014 003e Token-Ring Adapter
1014 00cd Token-Ring Adapter + Wake-On-LAN
1014 00cf 16/4 Token-Ring Adapter Special
1014 00e4 High-Speed 100/16/4 Token-Ring Adapter
1014 00e5 16/4 Token-Ring Adapter 2 + Wake-On-LAN
+ 0045 SSA Adapter
0046 MPIC interrupt controller
0047 PCI to PCI Bridge
0048 PCI to PCI Bridge
+ 004e ATM Controller (14104e00)
+ 004f ATM Controller (14104f00)
+ 0050 ATM Controller (14105000)
0053 25 MBit ATM Controller
0057 MPEG PCI Bridge
005c i82557B 10/100
+ 007c ATM Controller (14107c00)
007d 3780IDSP [MWave]
+ 0090 GXT 3000P
+ 1014 008E GXT-3000P
0095 20H2999 PCI Docking Bridge
+ 00a5 ATM Controller (1410a500)
+ 00a6 ATM 155MBPS MM Controller (1410a600)
00b7 256-bit Graphics Rasterizer [Fire GL1]
1902 00b8 Fire GL1
+ 00be ATM 622MBPS Controller (1410be00)
+ 0142 Yotta Video Compositor Input
+ 1014 0143 Yotta Input Controller (ytin)
+ 0144 Yotta Video Compositor Output
+ 1014 0145 Yotta Output Controller (ytout)
ffff MPIC-2 interrupt controller
1015 LSI Logic Corp of Canada
1016 ICL Personal Systems
1077 VScom 400 4 port serial adaptor
9036 9036
9050 PCI <-> IOBus Bridge
+ 10b5 2273 SH-ARC SoHard ARCnet card
d84d 4006 EX-4006 1P
d84d 4008 EX-4008 1P EPP/ECP
d84d 4014 EX-4014 2P
11ae Aztech System Ltd
11af Avid Technology Inc.
11b0 V3 Semiconductor Inc.
+ 0002 V300PSC
0292 V292PBC [Am29030/40 Bridge]
0960 V96xPBC
c960 V96DPC
0458 LT WinModem
0459 LT WinModem
045a LT WinModem
- 0480 Venus WinModem (V90, 56KFlex)
+ 0480 Venus Modem (V90, 56KFlex)
11c2 Sand Microelectronics
11c3 NEC Corp
11c4 Document Technologies, Inc
139c 0017 Raven
14af 0002 Maxi Gamer Phoenix
3030 3030 Skywell Magic TwinPower
- 0004 Voodoo Banshee
+ 0004 Voodoo Banshee [Velocity 100]
0005 Voodoo 3
121a 0004 Voodoo3 AGP
121a 0030 Voodoo3 AGP
12ad Multidata GmbH
12ae Alteon Networks Inc.
0001 AceNIC Gigabit Ethernet
+ 1410 0104 Gigabit Ethernet-SX PCI Adapter (14100401)
12af TDK USA Corp
12b0 Jorge Scientific Corp
12b1 GammaLink
156f M-Systems Flash Disk Pioneers Ltd
1570 Lecroy Corp
1571 Contemporary Controls
+ a001 CCSI PCI20-485 ARCnet
+ a002 CCSI PCI20-485D ARCnet
+ a003 CCSI PCI20-485X ARCnet
+ a004 CCSI PCI20-CXB ARCnet
+ a005 CCSI PCI20-CXS ARCnet
+ a006 CCSI PCI20-FOG-SMA ARCnet
+ a007 CCSI PCI20-FOG-ST ARCnet
+ a008 CCSI PCI20-TB5 ARCnet
+ a009 CCSI PCI20-5-485 5Mbit ARCnet
+ a00a CCSI PCI20-5-485D 5Mbit ARCnet
+ a00b CCSI PCI20-5-485X 5Mbit ARCnet
+ a00c CCSI PCI20-5-FOG-ST 5Mbit ARCnet
+ a00d CCSI PCI20-5-FOG-SMA 5Mbit ARCnet
+ a201 CCSI PCI22-485 10Mbit ARCnet
+ a202 CCSI PCI22-485D 10Mbit ARCnet
+ a203 CCSI PCI22-485X 10Mbit ARCnet
+ a204 CCSI PCI22-CHB 10Mbit ARCnet
+ a205 CCSI PCI22-FOG_ST 10Mbit ARCnet
+ a206 CCSI PCI22-THB 10Mbit ARCnet
1572 Otis Elevator Company
1573 Lattice - Vantis
1574 Fairchild Semiconductor
45fb Baldor Electric Company
4680 Umax Computer Corp
4843 Hercules Computer Technology Inc
+4916 RedCreek Communications Inc
+ 1960 RedCreek PCI adapter
4943 Growth Networks
4978 Axil Computer Inc
4a14 NetVin
01 Token ring network controller
02 FDDI network controller
03 ATM network controller
+ 04 ISDN controller
80 Network controller
C 03 Display controller
00 VGA compatible controller
08 RACEway bridge
00 Transparent mode
01 Endpoint mode
+ 09 Semi-transparent PCI-to-PCI bridge
+ 40 Primary bus towards host CPU
+ 80 Secondary bus towards host CPU
+ 0a InfiniBand to PCI host bridge
80 Bridge
C 07 Communication controller
00 Serial controller
Fe USB Device
04 Fiber Channel
05 SMBus
+ 06 InfiniBand
C 0d Wireless controller
00 IRDA controller
01 Consumer IR controller
04 Satellite data communication controller
C 10 Encryption controller
00 Network and computing encryption device
- 01 Entertainment encryption device
+ 10 Entertainment encryption device
80 Encryption controller
C 11 Signal processing controller
00 DPIO module
+ 01 Performance counters
+ 10 Communication synchronizer
80 Signal processing controller
*eof = 1;
pci_for_each_dev(dev) {
- nprinted = sprint_dev_config(dev, buf + len, count - len);
+ nprinted = sprint_dev_config(dev, buf + len, PAGE_SIZE - len);
if (nprinted < 0) {
*eof = 0;
break;
busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL);
busy->erase = erase;
busy->client = handle;
- busy->timeout.prev = busy->timeout.next = NULL;
+ init_timer(&busy->timeout);
busy->timeout.data = (u_long)busy;
busy->timeout.function = &handle_erase_timeout;
busy->prev = busy->next = NULL;
init_waitqueue_head(&s->queue);
init_waitqueue_head(&s->request);
s->handle = NULL;
- s->removal.prev = s->removal.next = NULL;
+ init_timer(&s->removal);
s->removal.data = i;
s->removal.function = &handle_removal;
s->bind = NULL;
/* Set up polling */
poll_timer.function = &tcic_timer;
poll_timer.data = 0;
- poll_timer.prev = poll_timer.next = NULL;
+ init_timer(&poll_timer);
/* Build interrupt mask */
printk(", %d sockets\n" KERN_INFO " irq list (", sockets);
/* Function support */
struct trident_channel *(*alloc_pcm_channel)(struct trident_card *);
struct trident_channel *(*alloc_rec_pcm_channel)(struct trident_card *);
- void (*free_pcm_channel)(struct trident_card *, int chan);
+ void (*free_pcm_channel)(struct trident_card *, unsigned int chan);
void (*address_interrupt)(struct trident_card *);
};
#endif
}
-static int trident_check_channel_interrupt(struct trident_card * card, int channel)
+static u32 trident_get_interrupt_mask (struct trident_card * card,
+ unsigned int b)
{
- unsigned int mask = 1 << (channel & 0x1f);
- struct trident_pcm_bank *bank = &card->banks[channel >> 5];
- u32 reg, addr = bank->addresses->aint;
+ struct trident_pcm_bank *bank = &card->banks[b];
+ u32 addr = bank->addresses->aint;
+ return inl(TRID_REG(card, addr));
+}
- reg = inl(TRID_REG(card, addr));
+static int trident_check_channel_interrupt(struct trident_card * card,
+ unsigned int channel)
+{
+ unsigned int mask = 1 << (channel & 0x1f);
+ u32 reg = trident_get_interrupt_mask (card, channel >> 5);
#ifdef DEBUG
if (reg & mask)
return (reg & mask) ? TRUE : FALSE;
}
-static void trident_ack_channel_interrupt(struct trident_card * card, int channel)
+static void trident_ack_channel_interrupt(struct trident_card * card,
+ unsigned int channel)
{
unsigned int mask = 1 << (channel & 0x1f);
struct trident_pcm_bank *bank = &card->banks[channel >> 5];
int idx;
bank = &card->banks[BANK_B];
- if (bank->bitmap == ~0UL) {
- /* no more free channels avaliable */
- printk(KERN_ERR "trident: no more channels available on Bank B.\n");
- return NULL;
- }
+
for (idx = 31; idx >= 0; idx--) {
if (!(bank->bitmap & (1 << idx))) {
struct trident_channel *channel = &bank->channels[idx];
return channel;
}
}
+
+ /* no more free channels avaliable */
+ printk(KERN_ERR "trident: no more channels available on Bank B.\n");
return NULL;
}
bank = &card->banks[BANK_A];
- if (bank->bitmap == ~0UL) {
- /* no more free channels avaliable */
- printk(KERN_ERR "trident: no more channels available on Bank B.\n");
- return NULL;
- }
- for (idx = 0; idx <= 31; idx++) {
+ for (idx = ALI_PCM_OUT_CHANNEL_FIRST; idx <= ALI_PCM_OUT_CHANNEL_LAST ; idx++) {
if (!(bank->bitmap & (1 << idx))) {
struct trident_channel *channel = &bank->channels[idx];
bank->bitmap |= 1 << idx;
return channel;
}
}
+
+ /* no more free channels avaliable */
+ printk(KERN_ERR "trident: no more channels available on Bank B.\n");
return NULL;
}
}
-static void trident_free_pcm_channel(struct trident_card *card, int channel)
+static void trident_free_pcm_channel(struct trident_card *card,
+ unsigned int channel)
{
int bank;
bank = channel >> 5;
channel = channel & 0x1f;
- if (card->banks[bank].bitmap & (1 << (channel))) {
- card->banks[bank].bitmap &= ~(1 << (channel));
- }
+ card->banks[bank].bitmap &= ~(1 << (channel));
}
-static void ali_free_pcm_channel(struct trident_card *card, int channel)
+static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel)
{
int bank;
bank = channel >> 5;
channel = channel & 0x1f;
- if (card->banks[bank].bitmap & (1 << (channel))) {
- card->banks[bank].bitmap &= ~(1 << (channel));
- }
+ card->banks[bank].bitmap &= ~(1 << (channel));
}
if (channel > 63)
return FALSE;
- /* select hardware channel to write */
+ /* select hardware channel to write */
outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));
- /* output the channel registers */
+
+ /* Output the channel registers, but don't write register
+ three to an ALI chip. */
+
for (i = 0; i < CHANNEL_REGS; i++) {
+ if (i == 3 && card->pci_id == PCI_DEVICE_ID_ALI_5451)
+ continue;
outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));
- if (i == 2)
- if (card->pci_id == PCI_DEVICE_ID_ALI_5451)
- i++; //skip i=3
}
return TRUE;
static void ali_address_interrupt(struct trident_card *card)
{
int i;
- struct trident_state *state;
-
+ u32 mask = trident_get_interrupt_mask (card, BANK_A);
+
+#ifdef DEBUG
+ /* Sanity check to make sure that every state has a channel
+ and vice versa. */
+ u32 done = 0;
+ unsigned ns = 0;
+ unsigned nc = 0;
for (i = 0; i < NR_HW_CH; i++) {
- if (trident_check_channel_interrupt(card, i)) {
- trident_ack_channel_interrupt(card, i);
- if ((state = card->states[i]) != NULL) {
- state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
- trident_update_ptr(state);
- } else {
+ if (card->banks[BANK_A].bitmap & (1<<i))
+ nc ++;
+
+ if (card->states[i]) {
+ u32 bit = 1 << card->states[i]->dmabuf.channel->num;
+ if (bit & done)
+ printk (KERN_ERR "trident: channel allocated to two states\n");
+ ns++;
+
+ done |= bit;
+ }
+ }
+ if (ns != nc)
+ printk (KERN_ERR "trident: number of states != number of channels\n");
+#endif
+
+ for (i = 0; mask && i < NR_HW_CH; i++) {
+ struct trident_state *state = card->states[i];
+ if (!state)
+ continue;
+
+ trident_ack_channel_interrupt(card, state->dmabuf.channel->num);
+ mask &= ~ (1<<state->dmabuf.channel->num);
+ state->dmabuf.update_flag |= ALI_ADDRESS_INT_UPDATE;
+ trident_update_ptr(state);
+ }
+
+ if (mask)
+ for (i = 0; i < NR_HW_CH; i++)
+ if (mask & (1<<i)) {
printk("ali: spurious channel irq %d.\n", i);
trident_stop_voice(card, i);
trident_disable_voice_irq(card, i);
}
- }
- }
+
}
static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (dmabuf->channel == NULL) {
kfree (card->states[i]);
- card->states[i] = NULL;;
+ card->states[i] = NULL;
return -ENODEV;
}
state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
up(&state->open_sem);
+#ifdef DEBUG
+ printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n",
+ state->virt,
+ dmabuf->channel->num);
+#endif
MOD_INC_USE_COUNT;
return 0;
}
ALI_PCM_IN_CHANNEL = 31
};
+enum ali_pcm_out_channel_num {
+ ALI_PCM_OUT_CHANNEL_FIRST = 1,
+ ALI_PCM_OUT_CHANNEL_LAST = 30
+};
+
enum ali_ac97_power_control_bit {
ALI_EAPD_POWER_DOWN = 0x8000
};
/* Run it through the hoops (find a driver, etc) */
if (usb_new_device(usb)) {
+ usb_disconnect(&hub->children[port]);
/* Woops, disable the port */
dbg("hub: disabling port %d", port + 1);
usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 89, 85, 86, 87, 88,115,119,120,121,375,123, 90,
+ 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90,
284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
- if (mousedev_mix.open) {
+ if (mousedev_mix.open)
input_open_device(&mousedev->handle);
- mousedev_mix.open++;
- }
printk("mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
{
struct mousedev *mousedev = handle->private;
- if (mousedev->open || mousedev_mix.open) {
+ if (mousedev->open || mousedev_mix.open)
input_close_device(handle);
- mousedev_mix.open--;
- }
if (!--mousedev->used) {
input_unregister_minor(mousedev->devfs);
/* -*- linux-c -*- */
/*
- * Driver for USB Scanners (linux-2.3.99-pre3-7)
+ * Driver for USB Scanners (linux-2.3.99-pre6-3)
*
* Copyright (C) 1999, 2000 David E. Nelson
*
* - Removed unnessesary #include's
* - Scanner model now reported via syslog INFO after being detected
* *and* configured.
- * - Added user specified verdor:product USB ID's which can be passed
+ * - Added user specified vendor:product USB ID's which can be passed
* as module parameters.
*
*
* -EINTR.
*
*
+ * 0.4.3 4/30/2000
+ *
+ * - Added Umax Astra 2200 ID. Thanks to Flynn Marquardt
+ * <flynn@isr.uni-stuttgart.de>.
+ * - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>.
+ * - Added access time update for the device file courtesy of Paul
+ * Mackerras <paulus@linuxcare.com>. This allows a user space daemon
+ * to turn the lamp off for a Umax 1220U scanner after a prescribed
+ * time.
+ * - Fixed HP S20 ID's. Thanks to Ruud Linders <rlinders@xs4all.nl>.
+ * - Added Acer ScanPrisa 620U ID. Thanks to Oliver
+ * Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list.
+ * - Fixed bug in read_scanner for copy_to_user() function. The returned
+ * value should be 'partial' not 'this_read'.
+ * - Fixed bug in read_scanner. 'count' should be decremented
+ * by 'this_read' and not by 'partial'. This resulted in twice as many
+ * calls to read_scanner() for small amounts of data and possibly
+ * unexpected returns of '0'. Thanks to Karl Heinz
+ * Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu>
+ * for discovering this.
+ * - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a
+ * scanner lookup/ident table. Thanks Randy.
+ * - Documentation updates.
+ * - Added wait queues to read_scanner().
+ *
+ *
* TODO
*
* - Performance
* - Johannes Erdfelt for the loaning of a USB analyzer for tracking an
* issue with HP-4100 and uhci.
* - Adolfo Montero for his assistance.
- * - And anybody else who chimed in with reports and suggestions.
+ * - All the folks who chimed in with reports and suggestions.
+ * - All the developers that are working on USB SANE backends or other
+ * applications to use USB scanners.
*
* Performance:
*
* 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec
*/
+/*
+ * Scanner definitions, macros, module info,
+ * debug/ioctl/data_dump enable, and other constants.
+ */
#include "scanner.h"
-
static void
irq_scanner(struct urb *urb)
{
/*
* For the meantime, this is just a placeholder until I figure out what
- * all I want to do with it.
+ * all I want to do with it -- or somebody else for that matter.
*/
struct scn_usb_data *scn = urb->context;
dbg("open_scanner: scn_minor:%d", scn_minor);
if (!p_scn_table[scn_minor]) {
- err("open_scanner(%d): invalid scn_minor", scn_minor);
+ err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
dev = scn->scn_dev;
if (!dev) {
+ err("open_scanner(%d): Scanner device not present", scn_minor);
return -ENODEV;
}
if (!scn->present) {
+ err("open_scanner(%d): Scanner is not present", scn_minor);
return -ENODEV;
}
if (scn->isopen) {
+ err("open_scanner(%d): Scanner device is already open", scn_minor);
return -EBUSY;
}
+ init_waitqueue_head(&scn->rd_wait_q);
+
scn->isopen = 1;
file->private_data = scn; /* Used by the read and write metheds */
dev = scn->scn_dev;
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+
while (count > 0) {
if (signal_pending(current)) {
bytes_written += partial;
} else { /* No data written */
ret = 0;
- bytes_written = 0;
break;
}
}
int partial; /* Number of bytes successfully read */
int this_read; /* Max number of bytes to read */
int result;
+ int rd_expire = RD_EXPIRE;
char *ibuf;
bytes_read = 0;
ret = 0;
- while (count) {
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME; /* Update the
+ atime of
+ the device
+ node */
+
+ while (count > 0) {
if (signal_pending(current)) {
ret = -EINTR;
break;
this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
- result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, 120*HZ);
- dbg("read stats(%d): result:%d this_read:%d partial:%d", scn_minor, result, this_read, partial);
+ result = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, scn->bulk_in_ep), ibuf, this_read, &partial, RD_NAK_TIMEOUT);
+ dbg("read stats(%d): result:%d this_read:%d partial:%d count:%d", scn_minor, result, this_read, partial, count);
- if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
- warn("read_scanner(%d): NAK received", scn_minor);
- ret = -ETIME;
- break;
+/*
+ * Scanners are sometimes inheriently slow since they are mechanical
+ * in nature. USB bulk reads tend to timeout while the scanner is
+ * positioning, resetting, warming up the lamp, etc if the timeout is
+ * set too low. A very long timeout parameter for bulk reads was used
+ * to overcome this limitation, but this sometimes resulted in folks
+ * having to wait for the timeout to expire after pressing Ctrl-C from
+ * an application. The user was sometimes left with the impression
+ * that something had hung or crashed when in fact the USB read was
+ * just waiting on data. So, the below code retains the same long
+ * timeout period, but splits it up into smaller parts so that
+ * Ctrl-C's are acted upon in a reasonable amount of time.
+ */
+
+ if (result == USB_ST_TIMEOUT && !partial) { /* Timeout
+ and no
+ data */
+ if (--rd_expire <= 0) {
+ warn("read_scanner(%d): excessive NAK's received", scn_minor);
+ ret = -ETIME;
+ break;
+ } else {
+ interruptible_sleep_on_timeout(&scn->rd_wait_q, RD_NAK_TIMEOUT);
+ continue;
+ }
} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
warn("read_scanner(%d): funky result:%d. Please notify the maintainer.", scn_minor, (int)result);
ret = -EIO;
#endif
if (partial) { /* Data returned */
- if (copy_to_user(buffer, ibuf, this_read)) {
+ if (copy_to_user(buffer, ibuf, partial)) {
ret = -EFAULT;
break;
}
- count -= partial;
- bytes_read += partial;
+ count -= this_read; /* Compensate for short reads */
+ bytes_read += partial; /* Keep tally of what actually was read */
buffer += partial;
-
} else {
ret = 0;
break;
}
-
}
return ret ? ret : bytes_read;
struct usb_endpoint_descriptor *endpoint;
int ep_cnt;
+ int ix;
kdev_t scn_minor;
* Until we detect a device which is pleasing, we silently punt.
*/
- do {
- if (dev->descriptor.idVendor == 0x03f0) { /* Hewlett Packard */
- if (dev->descriptor.idProduct == 0x0205 || /* 3300C */
- dev->descriptor.idProduct == 0x0101 || /* 4100C */
- dev->descriptor.idProduct == 0x0105 || /* 4200C */
- dev->descriptor.idProduct == 0x0202 || /* PhotoSmart S20 */
- dev->descriptor.idProduct == 0x0401 || /* 5200C */
- dev->descriptor.idProduct == 0x0201 || /* 6200C */
- dev->descriptor.idProduct == 0x0601) { /* 6300C */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x06bd) { /* Agfa */
- if (dev->descriptor.idProduct == 0x0001 || /* SnapScan 1212U */
- dev->descriptor.idProduct == 0x2061 || /* Another SnapScan 1212U (?) */
- dev->descriptor.idProduct == 0x0100) { /* SnapScan Touch */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x1606) { /* Umax */
- if (dev->descriptor.idProduct == 0x0010 || /* Astra 1220U */
- dev->descriptor.idProduct == 0x0030 || /* Astra 2000U */
- dev->descriptor.idProduct == 0x0002) { /* Astra 1236U */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x04b8) { /* Seiko/Epson Corp. */
- if (dev->descriptor.idProduct == 0x0101 || /* Perfection 636U and 636Photo */
- dev->descriptor.idProduct == 0x0103 || /* Perfection 610 */
- dev->descriptor.idProduct == 0x0104) { /* Perfection 1200U and 1200Photo */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x055f) { /* Mustek */
- if (dev->descriptor.idProduct == 0x0001) { /* 1200 CU */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x05da) { /* Microtek */
- if (dev->descriptor.idProduct == 0x0099 || /* ScanMaker X6 - X6U */
- dev->descriptor.idProduct == 0x0094 || /* Phantom 336CX - C3 */
- dev->descriptor.idProduct == 0x00a0 || /* Phantom 336CX - C3 #2 */
- dev->descriptor.idProduct == 0x009a || /* Phantom C6 */
- dev->descriptor.idProduct == 0x00a3 || /* ScanMaker V6USL */
- dev->descriptor.idProduct == 0x80a3 || /* ScanMaker V6USL #2 */
- dev->descriptor.idProduct == 0x80ac) { /* ScanMaker V6UL - SpicyU */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x0461) { /* Primax/Colorado */
- if (dev->descriptor.idProduct == 0x0300 || /* G2-300 #1 */
- dev->descriptor.idProduct == 0x0380 || /* G2-600 #1 */
- dev->descriptor.idProduct == 0x0301 || /* G2E-300 */
- dev->descriptor.idProduct == 0x0381 || /* ReadyScan 636i */
- dev->descriptor.idProduct == 0x0302 || /* G2-300 #2 */
- dev->descriptor.idProduct == 0x0382 || /* G2-600 #2 */
- dev->descriptor.idProduct == 0x0303 || /* G2E-300 */
- dev->descriptor.idProduct == 0x0383 || /* G2E-600 */
- dev->descriptor.idProduct == 0x0340 || /* Colorado USB 9600 */
- dev->descriptor.idProduct == 0x0360 || /* Colorado USB 19200 */
- dev->descriptor.idProduct == 0x0341 || /* Colorado 600u */
- dev->descriptor.idProduct == 0x0361) { /* Colorado 1200u */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x04a7) { /* Visioneer */
- if (dev->descriptor.idProduct == 0x0221 || /* OneTouch 5300 */
- dev->descriptor.idProduct == 0x0221 || /* OneTouch 7600 */
- dev->descriptor.idProduct == 0x0231) { /* 6100 */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x0458) { /* Genius */
- if(dev->descriptor.idProduct == 0x2001) { /* ColorPage-Vivid Pro */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == 0x04a5) { /* Acer */
- if(dev->descriptor.idProduct == 0x2060) { /* Prisa Acerscan 620U */
- valid_device = 1;
- break;
- }
- }
-
- if (dev->descriptor.idVendor == vendor && /* User specified */
- dev->descriptor.idProduct == product) { /* User specified */
+ for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct scanner_device); ix++) {
+ if ((dev->descriptor.idVendor == scanner_device_ids [ix].idVendor) &&
+ (dev->descriptor.idProduct == scanner_device_ids [ix].idProduct)) {
valid_device = 1;
break;
- }
-
-
- } while (0);
+ }
+ }
+ if (dev->descriptor.idVendor == vendor && /* User specified */
+ dev->descriptor.idProduct == product) { /* User specified */
+ valid_device = 1;
+ }
- if (!valid_device)
- return NULL; /* We didn't find anything pleasing */
-
+ if (!valid_device)
+ return NULL; /* We didn't find anything pleasing */
/*
* After this point we can be a little noisy about what we are trying to
+/*
+ * Driver for USB Scanners (linux-2.3.99-pre6-3)
+ *
+ * Copyright (C) 1999, 2000 David E. Nelson
+ *
+ * David E. Nelson (dnelson@jump.net)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/malloc.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
+#include <linux/sched.h>
// #define DEBUG
+#include <linux/usb.h>
+
+static __s32 vendor=-1, product=-1;
+
+MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
+MODULE_DESCRIPTION("USB Scanner Driver");
+
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+
/* Enable to activate the ioctl interface. This is mainly meant for */
/* development purposes until an ioctl number is officially registered */
// #define SCN_IOCTL
-#include <linux/usb.h>
-// #include "usb.h"
-
/* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */
#define IBUF_SIZE 32768
#define OBUF_SIZE 4096
+/* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
+#define RD_NAK_TIMEOUT (10*HZ) /* Number of X seconds to wait */
+#define RD_EXPIRE 12 /* Number of attempts to wait X seconds */
-/* FIXME: These are NOT registered ioctls()'s */
+/* FIXME: These are NOT registered ioctls()'s */
#define PV8630_IOCTL_INREQUEST 69
#define PV8630_IOCTL_OUTREQUEST 70
char present; /* Not zero if device is present */
char *obuf, *ibuf; /* transfer buffers */
char bulk_in_ep, bulk_out_ep, intr_ep; /* Endpoint assignments */
+ wait_queue_head_t rd_wait_q; /* read timeouts */
};
static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */};
-MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
-MODULE_DESCRIPTION("USB Scanner Driver");
-
-static __s32 vendor=-1, product=-1;
-MODULE_PARM(vendor, "i");
-MODULE_PARM_DESC(vendor, "User specified USB idVendor");
-
-MODULE_PARM(product, "i");
-MODULE_PARM_DESC(product, "User specified USB idProduct");
+/* table of scanners that may work with this driver */
+static const struct scanner_device {
+ __u16 idVendor;
+ __u16 idProduct;
+} scanner_device_ids [] = {
+ /* Acer */
+ { 0x04a5, 0x2060 }, /* Prisa Acerscan 620U & 640U (!) */
+ { 0x04a5, 0x2040 }, /* Prisa AcerScan 620U (!) */
+ /* Agfa */
+ { 0x06bd, 0x0001 }, /* SnapScan 1212U */
+ { 0x06bd, 0x2061 }, /* Another SnapScan 1212U (?) */
+ { 0x06bd, 0x0100 }, /* SnapScan Touch */
+ /* Colorado -- See Primax/Colorado below */
+ /* Epson -- See Seiko/Epson below */
+ /* Genius */
+ { 0x0458, 0x2001 }, /* ColorPage-Vivid Pro */
+ /* Hewlett Packard */
+ { 0x03f0, 0x0205 }, /* 3300C */
+ { 0x03f0, 0x0101 }, /* 4100C */
+ { 0x03f0, 0x0105 }, /* 4200C */
+ { 0x03f0, 0x0202 }, /* PhotoSmart S20 */
+ { 0x03f0, 0x0401 }, /* 5200C */
+ { 0x03f0, 0x0201 }, /* 6200C */
+ { 0x03f0, 0x0601 }, /* 6300C */
+ /* iVina */
+ { 0x0638, 0x0268 }, /* 1200U */
+ /* Microtek */
+ { 0x05da, 0x0099 }, /* ScanMaker X6 - X6U */
+ { 0x05da, 0x0094 }, /* Phantom 336CX - C3 */
+ { 0x05da, 0x00a0 }, /* Phantom 336CX - C3 #2 */
+ { 0x05da, 0x009a }, /* Phantom C6 */
+ { 0x05da, 0x00a3 }, /* ScanMaker V6USL */
+ { 0x05da, 0x80a3 }, /* ScanMaker V6USL #2 */
+ { 0x05da, 0x80ac }, /* ScanMaker V6UL - SpicyU */
+ /* Mustek */
+ { 0x055f, 0x0001 }, /* 1200 CU */
+ /* Primax/Colorado */
+ { 0x0461, 0x0300 }, /* G2-300 #1 */
+ { 0x0461, 0x0380 }, /* G2-600 #1 */
+ { 0x0461, 0x0301 }, /* G2E-300 #1 */
+ { 0x0461, 0x0381 }, /* ReadyScan 636i */
+ { 0x0461, 0x0302 }, /* G2-300 #2 */
+ { 0x0461, 0x0382 }, /* G2-600 #2 */
+ { 0x0461, 0x0303 }, /* G2E-300 #2 */
+ { 0x0461, 0x0383 }, /* G2E-600 */
+ { 0x0461, 0x0340 }, /* Colorado USB 9600 */
+ { 0x0461, 0x0360 }, /* Colorado USB 19200 */
+ { 0x0461, 0x0341 }, /* Colorado 600u */
+ { 0x0461, 0x0361 }, /* Colorado 1200u */
+ /* Seiko/Epson Corp. */
+ { 0x04b8, 0x0101 }, /* Perfection 636U and 636Photo */
+ { 0x04b8, 0x0103 }, /* Perfection 610 */
+ { 0x04b8, 0x0104 }, /* Perfection 1200U and 1200Photo */
+ /* Umax */
+ { 0x1606, 0x0010 }, /* Astra 1220U */
+ { 0x1606, 0x0002 }, /* Astra 1236U */
+ { 0x1606, 0x0030 }, /* Astra 2000U */
+ { 0x1606, 0x0230 }, /* Astra 2200U */
+ /* Visioneer */
+ { 0x04a7, 0x0221 }, /* OneTouch 5300 */
+ { 0x04a7, 0x0221 }, /* OneTouch 7600 duplicate ID (!) */
+ { 0x04a7, 0x0231 }, /* 6100 */
+};
/* Forward declarations */
static struct usb_driver scanner_driver;
{
struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
- uhci->rh.send = 0;
- del_timer(&uhci->rh.rh_int_timer);
-
+ if (uhci->rh.urb == urb) {
+ uhci->rh.send = 0;
+ del_timer(&uhci->rh.rh_int_timer);
+ }
return 0;
}
/*-------------------------------------------------------------------*/
* us a reasonable dynamic range for irq latencies.
*/
for (i = 0; i < 1024; i++) {
- struct uhci_td *irq = &uhci->skel_int2_td;
+ struct uhci_td *irq = &uhci->skel_int1_td;
if (i & 1) {
irq++;
if (!urb) /* just to be sure */
return -EINVAL;
+ if (!urb->dev || !urb->dev->bus)
+ return -ENODEV;
+
ohci = (ohci_t *) urb->dev->bus->hcpriv;
#ifdef DEBUG
return rh_unlink_urb (urb); /* a request to the virtual root hub */
if (urb->hcpriv) {
- if (urb->status == USB_ST_URB_PENDING) { /* URB active? */
+ /* URB active? */
+ if (urb->status == USB_ST_URB_PENDING && !ohci->disabled) {
urb_priv_t * urb_priv = urb->hcpriv;
urb_priv->state = URB_DEL;
/* we want to delete the TDs of an URB from an ed
- * request the deletion, it will be handled at the next USB-frame */
+ * request the deletion, it will be handled at the
+ * next USB-frame */
spin_lock_irqsave (&usb_ed_lock, flags);
ep_rm_ed (urb->dev, urb_priv->ed);
remove_wait_queue (&op_wakeup, &wait);
} else
urb_rm_priv (urb);
+
+ urb->status = -ENOENT; // mark urb as killed
+ if (urb->complete)
+ urb->complete ((struct urb *) urb);
usb_dec_dev_use (urb->dev);
}
return 0;
{
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __u16 bcdUSB; v1.0 */
+ 0x10, /* __u16 bcdUSB; v1.1 */
0x01,
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
0x00,
0xff /* __u8 ep_bInterval; 255 ms */
};
{
ohci_t * ohci = urb->dev->bus->hcpriv;
- ohci->rh.send = 0;
- del_timer (&ohci->rh.rh_int_timer);
+ if (ohci->rh.urb == urb) {
+ ohci->rh.send = 0;
+ del_timer (&ohci->rh.rh_int_timer);
+ }
return 0;
}
/*-------------------------------------------------------------------------*/
+/* reinitialize after controller reset */
+
+static void hc_reinit_ohci (ohci_t *ohci)
+{
+ int i;
+
+ /* for load balancing of the interrupt branches */
+ for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
+ for (i = 0; i < NUM_INTS; i++) ohci->hcca.int_table[i] = 0;
+
+ ohci->ed_rm_list [0] = NULL;
+ ohci->ed_rm_list [1] = NULL;
+
+ /* end of control and bulk lists */
+ ohci->ed_isotail = NULL;
+ ohci->ed_controltail = NULL;
+ ohci->ed_bulktail = NULL;
+}
+
/* allocate OHCI */
static ohci_t * hc_alloc_ohci (void * mem_base)
{
- int i;
ohci_t * ohci;
struct usb_bus * bus;
ohci->irq = -1;
ohci->regs = mem_base;
- /* for load ballancing of the interrupt branches */
- for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
- for (i = 0; i < NUM_INTS; i++) ohci->hcca.int_table[i] = 0;
-
- /* end of control and bulk lists */
- ohci->ed_isotail = NULL;
- ohci->ed_controltail = NULL;
- ohci->ed_bulktail = NULL;
-
bus = usb_alloc_bus (&sohci_device_operations);
if (!bus) {
free_pages ((unsigned long) ohci, 1);
return ohci;
}
+
/*-------------------------------------------------------------------------*/
/* De-allocate all resources.. */
if (ohci) {
switch (rqst) {
case PM_SUSPEND:
- dbg("USB-Bus suspend: %p", ohci);
- writel (ohci->hc_control = 0xFF, &ohci->regs->control);
+ /* act as if usb suspend can always be used */
+ dbg("USB suspend: %p", ohci->regs);
+ ohci->hc_control = OHCI_USB_SUSPEND;
+ writel (ohci->hc_control, &ohci->regs->control);
wait_ms (10);
break;
+
case PM_RESUME:
- dbg("USB-Bus resume: %p", ohci);
- writel (ohci->hc_control = 0x7F, &ohci->regs->control);
- wait_ms (20);
- writel (ohci->hc_control = 0xBF, &ohci->regs->control);
+ /* did we suspend, or were we powered off? */
+ ohci->hc_control = readl (&ohci->regs->control);
+ temp = ohci->hc_control & OHCI_CTRL_HCFS;
+ switch (temp) {
+
+ case OHCI_USB_RESET: // lost power
+ dbg("USB reset: %p", ohci->regs);
+ ohci->disabled = 1;
+ if (ohci->bus->root_hub)
+ usb_disconnect (&ohci->bus->root_hub);
+ hc_reinit_ohci (ohci);
+ if ((temp = hc_reset (ohci)) < 0
+ || (temp = hc_start (ohci)) < 0) {
+ ohci->disabled = 1;
+ err ("can't restart, %d", temp);
+ }
+ dbg ("reset done");
+ break;
+
+ case OHCI_USB_SUSPEND: // host wakeup
+ case OHCI_USB_RESUME: // remote wakeup
+ dbg("USB resume: %p", ohci->regs);
+ ohci->hc_control = OHCI_USB_RESUME;
+ writel (ohci->hc_control, &ohci->regs->control);
+ wait_ms (20);
+
+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ writel (ohci->hc_control, &ohci->regs->control);
+ break;
+
+ default:
+ warn ("odd PM_RESUME");
+ }
break;
}
}
/* we allocate one of these for every device that we remember */
struct us_data {
- struct us_data *next; /* next device */
+ struct us_data *next; /* next device */
/* the device we're working with */
- struct semaphore dev_semaphore; /* protect pusb_dev */
- struct usb_device *pusb_dev; /* this usb_device */
+ struct semaphore dev_semaphore; /* protect pusb_dev */
+ struct usb_device *pusb_dev; /* this usb_device */
unsigned int flags; /* from filter initially */
/* information about the device -- always good */
- char vendor[32];
- char product[32];
- char serial[32];
- char *transport_name;
- char *protocol_name;
- __u8 subclass;
- __u8 protocol;
+ char vendor[USB_STOR_STRING_LEN];
+ char product[USB_STOR_STRING_LEN];
+ char serial[USB_STOR_STRING_LEN];
+ char *transport_name;
+ char *protocol_name;
+ u8 subclass;
+ u8 protocol;
/* information about the device -- only good if device is attached */
- __u8 ifnum; /* interface number */
- __u8 ep_in; /* bulk in endpoint */
- __u8 ep_out; /* bulk out endpoint */
- __u8 ep_int; /* interrupt endpoint */
- __u8 ep_interval; /* interrupt interval */
+ u8 ifnum; /* interface number */
+ u8 ep_in; /* bulk in endpoint */
+ u8 ep_out; /* bulk out endpoint */
+ struct usb_endpoint_descriptor *ep_int; /* interrupt endpoint */
/* function pointers for this device */
- trans_cmnd transport; /* transport function */
- trans_reset transport_reset; /* transport device reset */
- proto_cmnd proto_handler; /* protocol handler */
+ trans_cmnd transport; /* transport function */
+ trans_reset transport_reset; /* transport device reset */
+ proto_cmnd proto_handler; /* protocol handler */
/* SCSI interfaces */
- GUID(guid); /* unique dev id */
+ GUID(guid); /* unique dev id */
struct Scsi_Host *host; /* our dummy host data */
- Scsi_Host_Template htmplt; /* own host template */
- int host_number; /* to find us */
- int host_no; /* allocated by scsi */
- Scsi_Cmnd *srb; /* current srb */
+ Scsi_Host_Template htmplt; /* own host template */
+ int host_number; /* to find us */
+ int host_no; /* allocated by scsi */
+ Scsi_Cmnd *srb; /* current srb */
/* thread information */
Scsi_Cmnd *queue_srb; /* the single queue slot */
- int action; /* what to do */
- int pid; /* control thread */
+ int action; /* what to do */
+ int pid; /* control thread */
/* interrupt info for CBI devices -- only good if attached */
- struct semaphore ip_waitq; /* for CBI interrupts */
- __u16 ip_data; /* interrupt data */
- int ip_wanted; /* is an IRQ expected? */
- void *irq_handle; /* for USB int requests */
- unsigned int irqpipe; /* pipe for release_irq */
+ struct semaphore ip_waitq; /* for CBI interrupts */
+ int ip_wanted; /* is an IRQ expected? */
+
+ struct semaphore irq_urb_sem; /* to protect irq_urb */
+ struct urb *irq_urb; /* for USB int requests */
+ unsigned char irqbuf[2]; /* buffer for USB IRQ */
/* mutual exclusion structures */
- struct semaphore notify; /* thread begin/end */
- struct semaphore sleeper; /* to sleep the thread on */
- struct semaphore queue_exclusion; /* to protect data structs */
+ struct semaphore notify; /* thread begin/end */
+ struct semaphore sleeper; /* to sleep the thread on */
+ struct semaphore queue_exclusion; /* to protect data structs */
};
/*
* Transfer one SCSI scatter-gather buffer via bulk transfer
*
* Note that this function is necessary because we want the ability to
- * use scatter-gather memory. Good performance is achived by a combination
+ * use scatter-gather memory. Good performance is achieved by a combination
* of scatter-gather and clustering (which makes each chunk bigger).
*
* Note that the lower layer will always retry when a NAK occurs, up to the
/* transfer the data */
US_DEBUGP("Bulk xfer 0x%x(%d)\n", (unsigned int)buf, length);
- result = usb_bulk_msg(us->pusb_dev, pipe, buf, length, &partial, HZ);
+ result = usb_bulk_msg(us->pusb_dev, pipe, buf, length, &partial, 5*HZ);
US_DEBUGP("bulk_msg returned %d xferred %d/%d\n",
result, partial, length);
*/
sg = (struct scatterlist *) srb->request_buffer;
for (i = 0; i < srb->use_sg; i++) {
- result = us_transfer_partial(us, pipe, sg[i].address,
+ result = us_transfer_partial(us, pipe, sg[i].address,
sg[i].length);
if (result)
break;
}
else
/* no scatter-gather, just make the request */
- result = us_transfer_partial(us, pipe, srb->request_buffer,
+ result = us_transfer_partial(us, pipe, srb->request_buffer,
srb->request_bufflen);
/* return the result in the data structure itself */
struct scatterlist *sg;
/* support those devices which need the length calculated
- * differently
+ * differently
*/
if (us->flags & US_FL_ALT_LENGTH) {
if (srb->cmnd[0] == INQUIRY) {
srb->cmnd[3] = 0;
srb->cmnd[4] = 18;
srb->cmnd[5] = 0;
-
+
/* set the buffer length for transfer */
old_request_buffer = srb->request_buffer;
old_request_bufflen = srb->request_bufflen;
- old_sg = srb->use_sg;
+ old_sg = srb->use_sg;
srb->use_sg = 0;
srb->request_bufflen = 18;
srb->request_buffer = srb->sense_buffer;
/* issue the auto-sense command */
temp_result = us->transport(us->srb, us);
- if (temp_result == USB_STOR_TRANSPORT_ERROR) {
+ if (temp_result != USB_STOR_TRANSPORT_GOOD) {
/* FIXME: we need to invoke a transport reset here */
US_DEBUGP("-- auto-sense failure\n");
srb->result = DID_ERROR << 16;
/*
* Control/Bulk/Interrupt transport
*/
-static int CBI_irq(int state, void *buffer, int len, void *dev_id)
+static void CBI_irq(struct urb *urb)
{
- struct us_data *us = (struct us_data *)dev_id;
+ struct us_data *us = (struct us_data *)urb->context;
US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no);
- US_DEBUGP("-- IRQ data length is %d\n", len);
- US_DEBUGP("-- IRQ state is %d\n", state);
+ US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length);
+ US_DEBUGP("-- IRQ state is %d\n", urb->status);
/* is the device removed? */
- if (state != -ENOENT) {
+ if (urb->status != -ENOENT) {
/* save the data for interpretation later */
- us->ip_data = le16_to_cpup((__u16 *)buffer);
- US_DEBUGP("-- Interrupt Status 0x%x\n", us->ip_data);
-
+ US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n",
+ ((unsigned char*)urb->transfer_buffer)[0],
+ ((unsigned char*)urb->transfer_buffer)[1]);
+
+
/* was this a wanted interrupt? */
if (us->ip_wanted) {
us->ip_wanted = 0;
US_DEBUGP("ERROR: Unwanted interrupt received!\n");
} else
US_DEBUGP("-- device has been removed\n");
-
- /* This return code is truly meaningless -- and I mean truly. It gets
- * ignored by other layers. It used to indicate if we wanted to get
- * another interrupt or disable the interrupt callback
- */
- return 0;
}
static int CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* STALL must be cleared when they are detected */
if (result == -EPIPE) {
US_DEBUGP("-- Stall on control pipe. Clearing\n");
- result = usb_clear_halt(us->pusb_dev,
+ result = usb_clear_halt(us->pusb_dev,
usb_sndctrlpipe(us->pusb_dev,
0));
US_DEBUGP("-- usb_clear_halt() returns %d\n", result);
return USB_STOR_TRANSPORT_ERROR;
}
- US_DEBUGP("Got interrupt data 0x%x\n", us->ip_data);
+ US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n",
+ ((unsigned char*)us->irq_urb->transfer_buffer)[0],
+ ((unsigned char*)us->irq_urb->transfer_buffer)[1]);
/* UFI gives us ASC and ASCQ, like a request sense
*
srb->cmnd[0] == INQUIRY)
return USB_STOR_TRANSPORT_GOOD;
else
- if (us->ip_data)
+ if (((unsigned char*)us->irq_urb->transfer_buffer)[0])
return USB_STOR_TRANSPORT_FAILED;
else
return USB_STOR_TRANSPORT_GOOD;
* The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error
*/
- switch ((us->ip_data & 0xFF0F)) {
- case 0x0000:
+ if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) {
+ US_DEBUGP("CBI IRQ data showed reserved bType\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) {
+ case 0x00:
return USB_STOR_TRANSPORT_GOOD;
- case 0x0001:
+ case 0x01:
return USB_STOR_TRANSPORT_FAILED;
default:
return USB_STOR_TRANSPORT_ERROR;
int partial;
/* set up the command wrapper */
- bcb.Signature = US_BULK_CB_SIGN;
- bcb.DataTransferLength = us_transfer_length(srb, us);
+ bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcb.DataTransferLength = cpu_to_le32(us_transfer_length(srb, us));
bcb.Flags = US_DIRECTION(srb->cmnd[0]) << 7;
bcb.Tag = srb->serial_number;
bcb.Lun = srb->cmnd[1] >> 5;
/* send it to out endpoint */
US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n",
- bcb.Signature, bcb.Tag, bcb.Lun, bcb.DataTransferLength,
- bcb.Flags, bcb.Length);
+ le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun,
+ bcb.DataTransferLength, bcb.Flags, bcb.Length);
result = usb_bulk_msg(us->pusb_dev, pipe, &bcb,
US_BULK_CB_WRAP_LEN, &partial, HZ*5);
US_DEBUGP("Bulk command transfer result=%d\n", result);
/* get CSW for device status */
US_DEBUGP("Attempting to get CSW...\n");
result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
- US_BULK_CS_WRAP_LEN, &partial, HZ);
+ US_BULK_CS_WRAP_LEN, &partial, HZ*2);
/* did the attempt to read the CSW fail? */
if (result == -EPIPE) {
US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
usb_clear_halt(us->pusb_dev, pipe);
-
+
/* get the status again */
US_DEBUGP("Attempting to get CSW (2nd try)...\n");
result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
- US_BULK_CS_WRAP_LEN, &partial, HZ);
+ US_BULK_CS_WRAP_LEN, &partial, HZ*2);
/* if it fails again, we need a reset and return an error*/
if (result == -EPIPE) {
/* check bulk status */
US_DEBUGP("Bulk status S 0x%x T 0x%x R %d V 0x%x\n",
- bcs.Signature, bcs.Tag, bcs.Residue, bcs.Status);
- if (bcs.Signature != US_BULK_CS_SIGN || bcs.Tag != bcb.Tag ||
+ le32_to_cpu(bcs.Signature), bcs.Tag,
+ bcs.Residue, bcs.Status);
+ if (bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) ||
+ bcs.Tag != bcb.Tag ||
bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
US_DEBUGP("Bulk logical error\n");
return USB_STOR_TRANSPORT_ERROR;
static void ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
{
int old_cmnd = 0;
-
+
/* Fix some commands -- this is a form of mode translation
* ATAPI devices only accept 12 byte long commands
*
srb->cmnd[0] = srb->cmnd[0] | 0x20;
break;
} /* end switch on cmnd[0] */
-
+
/* send the command to the transport layer */
invoke_transport(srb, us);
-
+
/* Fix the MODE_SENSE data if we translated the command
*/
if (old_cmnd == MODE_SENSE) {
static void ufi_command(Scsi_Cmnd *srb, struct us_data *us)
{
int old_cmnd = 0;
-
+
/* fix some commands -- this is a form of mode translation
* UFI devices only accept 12 byte long commands
*
srb->cmnd[10] = 0;
srb->cmnd[9] = 0;
- /* if we're sending data, we send all. If getting data,
+ /* if we're sending data, we send all. If getting data,
* get the minimum */
if (srb->cmnd[0] == MODE_SELECT)
srb->cmnd[8] = srb->cmnd[4];
srb->cmnd[7] = 0;
srb->cmnd[8] = 8;
break;
-
+
/* for REQUEST_SENSE, UFI devices only ever return 18 bytes */
case REQUEST_SENSE:
srb->cmnd[4] = 18;
* so some devices do not support them
*/
if (us->flags & US_FL_MODE_XLATE) {
-
+
/* translate READ_6 to READ_10 */
if (srb->cmnd[0] == 0x08) {
-
+
/* get the control */
srb->cmnd[9] = us->srb->cmnd[5];
-
+
/* get the length */
srb->cmnd[8] = us->srb->cmnd[6];
srb->cmnd[7] = 0;
-
+
/* set the reserved area to 0 */
srb->cmnd[6] = 0;
-
+
/* get LBA */
srb->cmnd[5] = us->srb->cmnd[3];
srb->cmnd[4] = us->srb->cmnd[2];
srb->cmnd[3] = 0;
srb->cmnd[2] = 0;
-
+
/* LUN and other info in cmnd[1] can stay */
-
+
/* fix command code */
srb->cmnd[0] = 0x28;
-
+
US_DEBUGP("Changing READ_6 to READ_10\n");
US_DEBUG(us_show_command(srb));
}
-
+
/* translate WRITE_6 to WRITE_10 */
if (srb->cmnd[0] == 0x0A) {
-
+
/* get the control */
srb->cmnd[9] = us->srb->cmnd[5];
-
+
/* get the length */
srb->cmnd[8] = us->srb->cmnd[4];
srb->cmnd[7] = 0;
-
+
/* set the reserved area to 0 */
srb->cmnd[6] = 0;
-
+
/* get LBA */
srb->cmnd[5] = us->srb->cmnd[3];
srb->cmnd[4] = us->srb->cmnd[2];
srb->cmnd[2] = 0;
/* LUN and other info in cmnd[1] can stay */
-
+
/* fix command code */
srb->cmnd[0] = 0x2A;
SPRINTF(" Host scsi%d: usb-storage\n", hostno);
/* print product, vendor, and serial number strings */
- SPRINTF(" Vendor: %s\n", us->vendor);
+ SPRINTF(" Vendor: %s\n", us->vendor);
SPRINTF(" Product: %s\n", us->product);
SPRINTF("Serial Number: %s\n", us->serial);
SPRINTF(" Transport: %s\n", us->transport_name);
/* show the GUID of the device */
- SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
+ SPRINTF(" GUID: " GUID_FORMAT "\n", GUID_ARGS(us->guid));
/* release our lock on the data structures */
up(&us_list_semaphore);
action = us->action;
us->action = 0;
us->srb = us->queue_srb;
-
+
/* release the queue lock as fast as possible */
up(&(us->queue_exclusion));
sizeof(sense_notready));
us->srb->result = GOOD;
} else {
- memcpy(us->srb->sense_buffer,
- sense_notready,
+ memcpy(us->srb->sense_buffer,
+ sense_notready,
sizeof(sense_notready));
us->srb->result = CHECK_CONDITION;
}
up(&(us->dev_semaphore));
/* indicate that the command is done */
- US_DEBUGP("scsi cmd done, result=0x%x\n",
+ US_DEBUGP("scsi cmd done, result=0x%x\n",
us->srb->result);
us->srb->scsi_done(us->srb);
us->srb = NULL;
static struct us_unusual_dev us_unusual_dev_list[] = {
{ 0x057b, 0x0000, 0x0114,
"Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN },
+ { 0x059b, 0x0030, 0x0100,
+ "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN },
{ 0x0781, 0x0001, 0x0200,
- "Sandisk ImageMate", US_SC_SCSI, US_PR_CB,
+ "Sandisk ImageMate (w/eject button)", US_SC_SCSI, US_PR_CB,
US_FL_SINGLE_LUN | US_FL_START_STOP },
{ 0x0781, 0x0002, 0x0009,
- "** SECRET DEVICE **", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN },
- { 0x04e6, 0x0002, 0x0100,
- "Microtech USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ "** SECRET DEVICE **", US_SC_SCSI, US_PR_BULK,
+ US_FL_SINGLE_LUN | US_FL_IGNORE_SER },
{ 0x07af, 0x0005, 0x0100,
- "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ "Microtech USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0x04e6, 0x0002, 0x0100,
+ "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
+ { 0x04e6, 0x0006, 0x0100,
+ "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN},
+ { 0x03f0, 0x0107, 0x0200,
+ "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0},
{ 0x0000, 0x0000, 0x0,
"", 0, 0, 0}
};
* defining how we should support this device, or NULL if it's not in the
* list
*/
-static struct us_unusual_dev* us_find_dev(__u16 idVendor, __u16 idProduct,
- __u16 bcdDevice)
+static struct us_unusual_dev* us_find_dev(u16 idVendor, u16 idProduct,
+ u16 bcdDevice)
{
struct us_unusual_dev* ptr;
return ptr;
}
+/* Set up the IRQ pipe and handler
+ * Note that this function assumes that all the data in the us_data
+ * strucuture is current. This includes the ep_int field, which gives us
+ * the endpoint for the interrupt.
+ * Returns non-zero on failure, zero on success
+ */
+static int usb_stor_allocate_irq(struct us_data *ss)
+{
+ unsigned int pipe;
+ int maxp;
+ int result;
+
+ US_DEBUGP("Allocating IRQ for CBI transport\n");
+
+ /* lock access to the data structure */
+ down(&(ss->irq_urb_sem));
+
+ /* allocate the URB */
+ ss->irq_urb = usb_alloc_urb(0);
+ if (!ss->irq_urb) {
+ up(&(ss->irq_urb_sem));
+ US_DEBUGP("couldn't allocate interrupt URB");
+ return 1;
+ }
+
+ /* calculate the pipe and max packet size */
+ pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK);
+ maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe));
+ if (maxp > sizeof(ss->irqbuf))
+ maxp = sizeof(ss->irqbuf);
+
+ /* fill in the URB with our data */
+ FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp,
+ CBI_irq, ss, ss->ep_int->bInterval);
+
+ /* submit the URB for processing */
+ result = usb_submit_urb(ss->irq_urb);
+ US_DEBUGP("usb_submit_urb() returns %d\n", result);
+ if (result) {
+ usb_free_urb(ss->irq_urb);
+ up(&(ss->irq_urb_sem));
+ return 2;
+ }
+
+ /* unlock the data structure and return success */
+ up(&(ss->irq_urb_sem));
+ return 0;
+}
+
/* Probe to see if a new device is actually a SCSI device */
static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
{
int i;
char mf[USB_STOR_STRING_LEN]; /* manufacturer */
char prod[USB_STOR_STRING_LEN]; /* product */
- char serial[USB_STOR_STRING_LEN]; /* serial number */
- GUID(guid); /* Global Unique Identifier */
+ char serial[USB_STOR_STRING_LEN]; /* serial number */
+ GUID(guid); /* Global Unique Identifier */
unsigned int flags;
struct us_unusual_dev *unusual_dev;
struct us_data *ss = NULL;
/* these are temporary copies -- we test on these, then put them
* in the us-data structure
*/
- __u8 ep_in = 0;
- __u8 ep_out = 0;
- __u8 ep_int = 0;
- __u8 ep_interval = 0;
- __u8 subclass = 0;
- __u8 protocol = 0;
+ struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_out = NULL;
+ struct usb_endpoint_descriptor *ep_int = NULL;
+ u8 subclass = 0;
+ u8 protocol = 0;
/* the altsettting 0 on the interface we're probing */
struct usb_interface_descriptor *altsetting =
/* BULK in or out? */
if (altsetting->endpoint[i].bEndpointAddress &
USB_DIR_IN)
- ep_in = altsetting->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ ep_in = &altsetting->endpoint[i];
else
- ep_out = altsetting->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ ep_out = &altsetting->endpoint[i];
}
/* is it an interrupt endpoint? */
if ((altsetting->endpoint[i].bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
- ep_int = altsetting->endpoint[i].bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
- ep_interval = altsetting->endpoint[i].bInterval;
+ ep_int = &altsetting->endpoint[i];
}
}
- US_DEBUGP("Endpoints: In %d Out %d Int %d (Period %d)\n",
- ep_in, ep_out, ep_int, ep_interval);
+ US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n",
+ ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);
/* set the interface -- STALL is an acceptable response here */
result = usb_set_interface(dev, altsetting->bInterfaceNumber, 0);
/* Do some basic sanity checks, and bail if we find a problem */
if (!ep_in || !ep_out || (protocol == US_PR_CBI && !ep_int)) {
- US_DEBUGP("Sanity check failed. Rejecting device.\n");
+ US_DEBUGP("Sanity check failed. Rejecting device.\n");
return NULL;
}
/* clear the GUID and fetch the strings */
GUID_CLEAR(guid);
if (dev->descriptor.iManufacturer)
- usb_string(dev, dev->descriptor.iManufacturer, mf,
- sizeof(mf));
+ usb_string(dev, dev->descriptor.iManufacturer,
+ mf, sizeof(mf));
if (dev->descriptor.iProduct)
- usb_string(dev, dev->descriptor.iProduct, prod,
- sizeof(prod));
- if (dev->descriptor.iSerialNumber)
- usb_string(dev, dev->descriptor.iSerialNumber, serial,
- sizeof(serial));
+ usb_string(dev, dev->descriptor.iProduct,
+ prod, sizeof(prod));
+ if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER))
+ usb_string(dev, dev->descriptor.iSerialNumber,
+ serial, sizeof(serial));
/* Create a GUID for this device */
if (dev->descriptor.iSerialNumber && serial[0]) {
ss->ifnum = ifnum;
ss->pusb_dev = dev;
- /* hook up the IRQ handler again */
- if (ss->protocol == US_PR_CBI) {
- /* set up so we'll wait for notification */
- init_MUTEX_LOCKED(&(ss->ip_waitq));
-
- /* set up the IRQ pipe and handler */
- US_DEBUGP("Allocating IRQ for CBI transport\n");
- ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
- result = usb_request_irq(ss->pusb_dev, ss->irqpipe,
- CBI_irq, ss->ep_interval,
- (void *)ss,
- &(ss->irq_handle));
- US_DEBUGP("-- usb_request_irq returned %d\n", result);
- }
+ /* copy over the endpoint data */
+ if (ep_in)
+ ss->ep_in = ep_in->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ if (ep_out)
+ ss->ep_out = ep_out->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ ss->ep_int = ep_int;
+
+ /* allocate an IRQ callback if one is needed */
+ if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
+ return NULL;
} else {
- /* New device -- Allocate memory and initialize */
+ /* New device -- allocate memory and initialize */
US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data),
/* Initialize the mutexes only when the struct is new */
init_MUTEX_LOCKED(&(ss->sleeper));
init_MUTEX_LOCKED(&(ss->notify));
+ init_MUTEX_LOCKED(&(ss->ip_waitq));
init_MUTEX(&(ss->queue_exclusion));
+ init_MUTEX(&(ss->irq_urb_sem));
init_MUTEX(&(ss->dev_semaphore));
/* copy over the subclass and protocol data */
ss->flags = flags;
/* copy over the endpoint data */
- ss->ep_in = ep_in;
- ss->ep_out = ep_out;
+ if (ep_in)
+ ss->ep_in = ep_in->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
+ if (ep_out)
+ ss->ep_out = ep_out->bEndpointAddress &
+ USB_ENDPOINT_NUMBER_MASK;
ss->ep_int = ep_int;
- ss->ep_interval = ep_interval;
/* establish the connection to the new device */
ss->ifnum = ifnum;
case US_SC_QIC:
ss->protocol_name = "QIC-157";
- US_DEBUGP("Sorry, device not supported. Please\n");
+ US_DEBUGP("Sorry, device not supported. Please\n");
US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n");
US_DEBUGP("if you see this message.\n");
up(&us_list_semaphore);
}
US_DEBUGP("Protocol: %s\n", ss->protocol_name);
- if (ss->protocol == US_PR_CBI) {
- /* set up so we'll wait for notification */
- init_MUTEX_LOCKED(&(ss->ip_waitq));
-
- /* set up the IRQ pipe and handler */
- US_DEBUGP("Allocating IRQ for CBI transport\n");
- ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
- result = usb_request_irq(ss->pusb_dev, ss->irqpipe,
- CBI_irq, ss->ep_interval,
- (void *)ss,
- &(ss->irq_handle));
- US_DEBUGP("-- usb_request_irq returned %d\n", result);
- }
+ /* allocate an IRQ callback if one is needed */
+ if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
+ return NULL;
/*
* Since this is a new device, we need to generate a scsi
*/
(struct us_data *)ss->htmplt.proc_dir = ss;
- /* start up our thread */
+ /* start up our control thread */
ss->pid = kernel_thread(usb_stor_control_thread, ss,
CLONE_FS | CLONE_FILES |
CLONE_SIGHAND);
return NULL;
}
- /* wait for it to start */
+ /* wait for the thread to start */
down(&(ss->notify));
- /* now register - our detect function will be called */
+ /* now register - our detect function will be called */
ss->htmplt.module = THIS_MODULE;
scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt));
int result;
US_DEBUGP("storage_disconnect() called\n");
-
+
/* this is the odd case -- we disconnected but weren't using it */
if (!ss) {
US_DEBUGP("-- device was not in use\n");
down(&(ss->dev_semaphore));
/* release the IRQ, if we have one */
- if (ss->irq_handle) {
+ down(&(ss->irq_urb_sem));
+ if (ss->irq_urb) {
US_DEBUGP("-- releasing irq handle\n");
- result = usb_release_irq(ss->pusb_dev, ss->irq_handle,
- ss->irqpipe);
- US_DEBUGP("-- usb_release_irq() returned %d\n", result);
- ss->irq_handle = NULL;
+ result = usb_unlink_urb(ss->irq_urb);
+ ss->irq_urb = NULL;
+ US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
+ usb_free_urb(ss->irq_urb);
}
+ up(&(ss->irq_urb_sem));
/* mark the device as gone */
ss->pusb_dev = NULL;
/* Sub Classes */
-#define US_SC_RBC 1 /* Typically, flash devices */
-#define US_SC_8020 2 /* CD-ROM */
-#define US_SC_QIC 3 /* QIC-157 Tapes */
-#define US_SC_UFI 4 /* Floppy */
-#define US_SC_8070 5 /* Removable media */
-#define US_SC_SCSI 6 /* Transparent */
+#define US_SC_RBC 0x01 /* Typically, flash devices */
+#define US_SC_8020 0x02 /* CD-ROM */
+#define US_SC_QIC 0x03 /* QIC-157 Tapes */
+#define US_SC_UFI 0x04 /* Floppy */
+#define US_SC_8070 0x05 /* Removable media */
+#define US_SC_SCSI 0x06 /* Transparent */
#define US_SC_MIN US_SC_RBC
#define US_SC_MAX US_SC_SCSI
/* Protocols */
-#define US_PR_CB 1 /* Control/Bulk w/o interrupt */
-#define US_PR_CBI 0 /* Control/Bulk/Interrupt */
+#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
+#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
#define US_PR_BULK 0x50 /* bulk only */
/*
- * Bulk only data structures (Zip 100, for example)
+ * Bulk only data structures
*/
/* command block wrapper */
__u8 CDB[16]; /* max command */
};
-#define US_BULK_CB_WRAP_LEN 31
-#define US_BULK_CB_SIGN 0x43425355
+#define US_BULK_CB_WRAP_LEN 31
+#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
#define US_BULK_FLAG_IN 1
#define US_BULK_FLAG_OUT 0
};
#define US_BULK_CS_WRAP_LEN 13
-#define US_BULK_CS_SIGN 0x53425355
+#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_PHASE 2
/*
* us_bulk_transfer() return codes
*/
-#define US_BULK_TRANSFER_GOOD 0
-#define US_BULK_TRANSFER_SHORT 1
+#define US_BULK_TRANSFER_GOOD 0
+#define US_BULK_TRANSFER_SHORT 1
#define US_BULK_TRANSFER_FAILED 2
/*
* Transport return codes
*/
-#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */
+#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */
#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */
#define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */
};
/* Flag definitions */
-#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
+#define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 comands for
- Win/MacOS compatibility */
-#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */
+ Win/MacOS compatibility */
+#define US_FL_START_STOP 0x00000004 /* ignore START_STOP commands */
#define US_FL_ALT_LENGTH 0x00000008 /* use the alternate algorithm for
- us_transfer_length() */
+ us_transfer_length() */
+#define US_FL_IGNORE_SER 0x00000010 /* Ignore the serial number given */
+
# Add fbmon.o back into obj-$(CONFIG_FB) in 2.5.x
obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o fbcon.o fonts.o
-obj-$(CONFIG_FB_COMPAT_XPMAC) += macmodes.o
+obj-$(CONFIG_PPC) += macmodes.o
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o
* - monitor sensing (DDC)
* - virtual display
* - other platform support (only ppc/x86 supported)
- * - PPLL_REF_DIV & XTALIN calculation -done for x86
- * - determine MCLK from previous setting -done for x86
- * - calculate XCLK, rather than probe BIOS
* - hardware cursor support
* - ioctl()'s
+ *
+ * Please cc: your patches to brad@neruo.com.
*/
/*
#endif
/* default mode */
-static struct fb_var_screeninfo default_var = {
+static struct fb_var_screeninfo default_var __initdata = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
};
/* packed BIOS settings */
+#ifndef CONFIG_PPC
#pragma pack(1)
typedef struct {
u8 clock_chip_type;
u32 XCLK_max_freq;
} PLL_BLOCK;
#pragma pack()
+#endif /* !CONFIG_PPC */
/* onboard memory information */
struct aty128_meminfo {
info->palette[j].blue = default_blu[k];
}
+ /* setup the DAC the way we like it */
dac = aty_ld_le32(DAC_CNTL);
- dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL | DAC_BLANKING);
+ dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
dac |= DAC_MASK;
aty_st_le32(DAC_CNTL, dac);
{ -1, VMODE_640_480_60 }, /* catch-all, must be last */
};
+#ifdef CONFIG_FB_COMPAT_XPMAC
struct fb_info *console_fb_info = NULL;
struct vc_mode display_info;
+
static u16 palette_red[16];
static u16 palette_green[16];
static u16 palette_blue[16];
};
-int console_getmode(struct vc_mode *);
-int console_setmode(struct vc_mode *, int);
-int console_setcmap(int, unsigned char *, unsigned char *, unsigned char *);
-int console_powermode(int);
-int mac_var_to_vmode(const struct fb_var_screeninfo *, int *, int *);
-
-
int console_getmode(struct vc_mode *mode)
{
*mode = display_info;
return 0;
}
-
int console_setmode(struct vc_mode *mode, int doit)
{
struct fb_var_screeninfo var;
return 0;
}
-
int console_setcmap(int n_entries, unsigned char *red, unsigned char *green,
unsigned char *blue)
{
return 0;
}
+int console_powermode(int mode)
+{
+ if (mode == VC_POWERMODE_INQUIRY)
+ return 0;
+ if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN)
+ return -EINVAL;
+ /* Not Supported */
+ return -ENXIO;
+}
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
/*
* Convert a MacOS vmode/cmode pair to a frame buffer video mode structure
}
-int console_powermode(int mode)
-{
- if (mode == VC_POWERMODE_INQUIRY)
- return 0;
- if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN)
- return -EINVAL;
- /* Not Supported */
- return -ENXIO;
-}
-
-
/*
* Convert a frame buffer video mode structure to a MacOS vmode/cmode pair
*/
/* Expiration-handling functions */
void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *);
+struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *, struct vfsmount *mnt);
/* Operations structures */
}
struct autofs_dir_ent *autofs_expire(struct super_block *sb,
- struct autofs_sb_info *sbi)
+ struct autofs_sb_info *sbi,
+ struct vfsmount *mnt)
{
struct autofs_dirhash *dh = &sbi->dirhash;
struct autofs_dir_ent *ent;
DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
continue;
}
+ mntget(mnt);
+ dget(dentry);
+ if (!follow_down(&mnt, &dentry)) {
+ dput(dentry);
+ mntput(mnt);
+ DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name));
+ continue;
+ }
+ while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
+ ;
+ dput(dentry);
- if ( may_umount(dentry->d_mounts->d_sb) == 0 ) {
+ if ( may_umount(mnt) == 0 ) {
+ mntput(mnt);
DPRINTK(("autofs: signaling expire on %s\n", ent->name));
return ent; /* Expirable! */
}
DPRINTK(("autofs: didn't expire due to may_umount: %s\n", ent->name));
+ mntput(mnt);
}
return NULL; /* No expirable entries */
}
/* Perform an expiry operation */
static inline int autofs_expire_run(struct super_block *sb,
struct autofs_sb_info *sbi,
+ struct vfsmount *mnt,
struct autofs_packet_expire *pkt_p)
{
struct autofs_dir_ent *ent;
pkt.hdr.type = autofs_ptype_expire;
if ( !sbi->exp_timeout ||
- !(ent = autofs_expire(sb,sbi)) )
+ !(ent = autofs_expire(sb,sbi,mnt)) )
return -EAGAIN;
pkt.len = ent->len;
case AUTOFS_IOC_SETTIMEOUT:
return autofs_get_set_timeout(sbi,(unsigned long *)arg);
case AUTOFS_IOC_EXPIRE:
- return autofs_expire_run(inode->i_sb,sbi,
+ return autofs_expire_run(inode->i_sb, sbi, filp->f_vfsmnt,
(struct autofs_packet_expire *)arg);
default:
return -ENOSYS;
nr++;
} while (i++, iblock++, (bh = bh->b_this_page) != head);
- ++current->maj_flt;
if (nr) {
if (Page_Uptodate(page))
BUG();
}
bh = bh->b_this_page;
} while (bh != head);
- if (rw == READ)
- ++current->maj_flt;
if ((rw == READ) && nr) {
if (Page_Uptodate(page))
BUG();
__get_free_pages(GFP_ATOMIC, order);
} while (hash_table == NULL && --order > 0);
printk("Buffer-cache hash table entries: %d (order: %d, %ld bytes)\n",
- nr_hash, order, (1UL<<order) * PAGE_SIZE);
+ nr_hash, order, (PAGE_SIZE << order));
if (!hash_table)
panic("Failed to allocate buffer hash table\n");
__get_free_pages(GFP_ATOMIC, order);
} while (dentry_hashtable == NULL && --order >= 0);
+ printk("Dentry-cache hash table entries: %d (order: %ld, %ld bytes)\n",
+ nr_hash, order, (PAGE_SIZE << order));
+
if (!dentry_hashtable)
panic("Failed to allocate dcache hash table\n");
- printk("VFS: DCACHE hash table configured to %d entries\n", nr_hash);
-
d = dentry_hashtable;
i = nr_hash;
do {
__get_free_pages(GFP_ATOMIC, order);
} while (inode_hashtable == NULL && --order >= 0);
+ printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n",
+ nr_hash, order, (PAGE_SIZE << order));
+
if (!inode_hashtable)
panic("Failed to allocate inode hash table\n");
- printk("VFS: INODE hash table configured to %d entries\n", nr_hash);
-
head = inode_hashtable;
i = nr_hash;
do {
block, offset, filp->f_pos);
printk("inode->i_size = %x\n",inode->i_size);
#endif
+ /* Next directory_record on next CDROM sector */
+ if (offset >= bufsize) {
+#ifdef DEBUG
+ printk("offset >= bufsize\n");
+#endif
+ brelse(bh);
+ offset = 0;
+ block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
+ if (!block)
+ return 0;
+ bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
+ if (!bh)
+ return 0;
+ continue;
+ }
+
de = (struct iso_directory_record *) (bh->b_data + offset);
if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
de_len = *(unsigned char *) de;
#ifdef DEBUG
- printk("de_len = %ld\n", de_len);
+ printk("de_len = %d\n", de_len);
#endif
CDROM sector. If we are at the end of the directory, we
kick out of the while loop. */
- if ((de_len == 0) || (offset >= bufsize) ) {
+ if (de_len == 0) {
brelse(bh);
- if (de_len == 0) {
- filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
- + ISOFS_BLOCK_SIZE);
- offset = 0;
- } else {
- offset -= bufsize;
- filp->f_pos += offset;
- }
+ filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
+ + ISOFS_BLOCK_SIZE);
+ offset = 0;
if (filp->f_pos >= inode->i_size)
return 0;
* within the RPC code when root squashing is suspected.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
} else {
dentry = lookup_one(name, dparent);
err = PTR_ERR(dentry);
- if (err)
+ if (IS_ERR(dentry))
goto out_nfserr;
/*
* check if we have crossed a mount point ...
*/
dchild = lookup_one(fname, dentry);
err = PTR_ERR(dchild);
- if(IS_ERR(dchild))
+ if (IS_ERR(dchild))
goto out_nfserr;
err = fh_compose(resfhp, fhp->fh_export, dchild);
O_TARGET := ntfs.o
O_OBJS := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o
M_OBJS := $(O_TARGET)
-EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"000410\"
+EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"000502\"
include $(TOPDIR)/Rules.make
* fs.c
* NTFS driver for Linux 2.3.x
*
- * Copyright (C) 2000, Anton Altaparmakov
* Copyright (C) 1995-1997, 1999 Martin von Löwis
* Copyright (C) 1996 Richard Russon
* Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 2000, Anton Altaparmakov
*/
#ifdef HAVE_CONFIG_H
return register_filesystem(&ntfs_fs_type);
}
-static __exit void exit_ntfs_fs(void)
+static void __exit exit_ntfs_fs(void)
{
SYSCTL(0);
ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
* Structure definitions
*
* Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 2000 Anton Altaparmakov
*/
/* Necessary forward definition */
ntfs_u32 at_standard_information;
ntfs_u32 at_attribute_list;
ntfs_u32 at_file_name;
+ ntfs_u32 at_volume_version;
ntfs_u32 at_security_descriptor;
+ ntfs_u32 at_volume_name;
+ ntfs_u32 at_volume_information;
ntfs_u32 at_data;
ntfs_u32 at_index_root;
ntfs_u32 at_index_allocation;
* Copyright (C) 1995-1997, 1999 Martin von Löwis
* Copyright (C) 1996-1997 Régis Duchesne
* Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2000 Anton Altparmakov
*/
#include "ntfstypes.h"
vol->at_standard_information=0x10;
vol->at_attribute_list=0x20;
vol->at_file_name=0x30;
+ vol->at_volume_version=0x40;
vol->at_security_descriptor=0x50;
+ vol->at_volume_name=0x60;
+ vol->at_volume_information=0x70;
vol->at_data=0x80;
vol->at_index_root=0x90;
vol->at_index_allocation=0xA0;
}else if(ntfs_ua_strncmp(name,"$FILE_NAME",64)==0){
vol->at_file_name=type;
check_type=0x30;
+ }else if(ntfs_ua_strncmp(name,"$VOLUME_VERSION",64)==0){
+ vol->at_volume_version=type;
+ check_type=0x40;
}else if(ntfs_ua_strncmp(name,"$SECURITY_DESCRIPTOR",64)==0){
- vol->at_file_name=type;
+ vol->at_security_descriptor=type;
+ check_type=0x50;
+ }else if(ntfs_ua_strncmp(name,"$VOLUME_NAME",64)==0){
+ vol->at_volume_name=type;
+ check_type=0x60;
+ }else if(ntfs_ua_strncmp(name,"$VOLUME_INFORMATION",64)==0){
+ vol->at_volume_information=type;
+ check_type=0x70;
}else if(ntfs_ua_strncmp(name,"$DATA",64)==0){
vol->at_data=type;
check_type=0x80;
}else if(ntfs_ua_strncmp(name,"$SYMBOLIC_LINK",64)==0 ||
ntfs_ua_strncmp(name,"$REPARSE_POINT",64)==0){
vol->at_symlink=type;
+ check_type=0xC0;
}
if(check_type && check_type!=type){
ntfs_error("Unexpected type %x for %x\n",type,check_type);
return error;
}
+/* ntfs_get_version will determine the NTFS version of the
+ volume and will return the version in a BCD format, with
+ the MSB being the major version number and the LSB the
+ minor one. Otherwise return <0 on error.
+ Example: version 3.1 will be returned as 0x0301.
+ This has the obvious limitation of not coping with version
+ numbers above 0x80 but that shouldn't be a problem... */
+int ntfs_get_version(ntfs_inode* volume)
+{
+ ntfs_attribute *volinfo;
+ int i;
+
+ volinfo = ntfs_find_attr(volume, volume->vol->at_volume_information, 0);
+ if (!volinfo)
+ return -EINVAL;
+ if (!volinfo->resident) {
+ ntfs_error("Volume information attribute is not resident!\n");
+ return -EINVAL;
+ }
+ return ((ntfs_u8*)volinfo->d.data)[8] << 8 | ((ntfs_u8*)volinfo->d.data)[9];
+}
+
int ntfs_load_special_files(ntfs_volume *vol)
{
int error;
- ntfs_inode upcase,attrdef;
+ ntfs_inode upcase, attrdef, volume;
vol->mft_ino=(ntfs_inode*)ntfs_calloc(3*sizeof(ntfs_inode));
error=ENOMEM;
error=ntfs_init_attrdef(&attrdef);
ntfs_clear_inode(&attrdef);
if(error)return error;
+
+ /* Check for NTFS version and if Win2k version (ie. 3.0+)
+ do not allow write access since the driver write support
+ is broken, especially for Win2k. */
+ ntfs_debug(DEBUG_BSD,"Going to load VOLUME\n");
+ error = ntfs_init_inode(&volume,vol,FILE_VOLUME);
+ if (error) return error;
+ if ((error = ntfs_get_version(&volume)) >= 0x0300) {
+ NTFS_SB(vol)->s_flags |= MS_RDONLY;
+ ntfs_error("Warning! NTFS volume version is Win2k+: Mounting read-only\n");
+ }
+ ntfs_clear_inode(&volume);
+ if (error < 0) return error;
+ ntfs_debug(DEBUG_BSD, "NTFS volume is version %d.%d\n", error >> 8, error & 0xff);
+
return 0;
}
return -1;
if(b[i]<a[i])
return 1;
+ if (a[i] == 0)
+ return 0;
}
return 0;
}
return -1;
if(b[i]<NTFS_GETU16(a+i))
return 1;
+ if (b[i] == 0)
+ return 0;
}
return 0;
}
error = -ENOMEM;
f1->f_dentry = f2->f_dentry = dget(d_alloc_root(inode));
+ /* MOUNT_REWRITE: set to pipefs internal vfsmnt */
+ f1->f_vfsmnt = f2->f_vfsmnt = NULL;
if (!f1->f_dentry)
goto close_f12_inode_i_j;
int proc_pid_cpu(struct task_struct*,char*);
/* MOUNT_REWRITE: make all files have non-NULL ->f_vfsmnt (pipefs, sockfs) */
+/* Until then... */
+#define NULL_VFSMNT /* remove as soon as pipefs and sockfs will be there */
+
static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
{
if (inode->u.proc_i.file) {
- if (inode->u.proc_i.file->f_vfsmnt) {
- *mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
- }
+#ifdef NULL_VFSMNT
+ if (!inode->u.proc_i.file->f_vfsmnt)
+ mntget(*mnt);
+ else
+#endif
+ *mnt = mntget(inode->u.proc_i.file->f_vfsmnt);
*dentry = dget(inode->u.proc_i.file->f_dentry);
return 0;
}
static int proc_permission(struct inode *inode, int mask)
{
struct dentry *de, *base, *root;
- struct super_block *our_sb, *sb, *below;
struct vfsmount *our_vfsmnt, *vfsmnt, *mnt;
if (standard_permission(inode, mask) != 0)
de = root;
mnt = vfsmnt;
- our_sb = base->d_inode->i_sb;
- sb = de->d_inode->i_sb;
- while (sb != our_sb) {
- de = sb->s_root->d_covers;
- below = de->d_inode->i_sb;
- if (sb == below)
+
+ while (vfsmnt != our_vfsmnt) {
+ if (vfsmnt == vfsmnt->mnt_parent)
goto out;
- sb = below;
+ de = vfsmnt->mnt_mountpoint;
+ vfsmnt = vfsmnt->mnt_parent;
}
if (!is_subdir(de, base))
{
struct inode *inode = dentry->d_inode;
int error;
+#ifdef NULL_VFSMNT
+ struct vfsmount *dummy = mntget(nd->mnt);
+#endif
/* We don't need a base pointer in the /proc filesystem */
dput(nd->dentry);
error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
out:
+#ifdef NULL_VFSMNT
+ mntput(dummy);
+#endif
return error;
}
*/
static struct file_system_type *file_systems = NULL;
-static spinlock_t file_systems_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
/* WARNING: This can be used only if we _already_ own a reference */
static void get_filesystem(struct file_system_type *fs)
return -EINVAL;
if (fs->next)
return -EBUSY;
- spin_lock(&file_systems_lock);
+ write_lock(&file_systems_lock);
p = find_filesystem(fs->name);
if (*p)
res = -EBUSY;
else
*p = fs;
- spin_unlock(&file_systems_lock);
+ write_unlock(&file_systems_lock);
return res;
}
{
struct file_system_type ** tmp;
- spin_lock(&file_systems_lock);
+ write_lock(&file_systems_lock);
tmp = &file_systems;
while (*tmp) {
if (fs == *tmp) {
*tmp = fs->next;
fs->next = NULL;
- spin_unlock(&file_systems_lock);
+ write_unlock(&file_systems_lock);
return 0;
}
tmp = &(*tmp)->next;
}
- spin_unlock(&file_systems_lock);
+ write_unlock(&file_systems_lock);
return -EINVAL;
}
return err;
err = -EINVAL;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
if (strcmp(tmp->name,name) == 0) {
err = index;
break;
}
}
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
putname(name);
return err;
}
struct file_system_type * tmp;
int len, res;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
for (tmp = file_systems; tmp; tmp = tmp->next, index--)
if (index <= 0 && try_inc_mod_count(tmp->owner))
break;
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
if (!tmp)
return -EINVAL;
struct file_system_type * tmp;
int index;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
;
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
return index;
}
int len = 0;
struct file_system_type * tmp;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
tmp = file_systems;
while (tmp && len < PAGE_SIZE - 80) {
len += sprintf(buf+len, "%s\t%s\n",
tmp->name);
tmp = tmp->next;
}
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
return len;
}
{
struct file_system_type *fs;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
if (!fs && (request_module(name) == 0)) {
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
fs = *(find_filesystem(name));
if (fs && !try_inc_mod_count(fs->owner))
fs = NULL;
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
}
return fs;
}
* give false negatives. The main reason why it's here is that we need
* a non-destructive way to look for easily umountable filesystems.
*/
- /* MOUNT_REWRITE: it should take vfsmount, not superblock */
-int may_umount(struct super_block *sb)
+int may_umount(struct vfsmount *mnt)
{
+ struct super_block * sb = mnt->mnt_sb;
struct dentry * root;
int count;
+ if (atomic_read(&mnt->mnt_count) > 2)
+ return -EBUSY;
+
+ if (mnt->mnt_instances.next != mnt->mnt_instances.prev)
+ return 0;
+
+ /*
+ * OK, at that point we have only one instance. We should have
+ * one active reference from ->s_root, one active reference
+ * from ->mnt_root (which may be different) and possibly one
+ * active reference from ->mnt_mountpoint (if mnt->mnt_parent == mnt).
+ * Anything above that means that tree is busy.
+ */
+
root = sb->s_root;
count = d_active_refs(root);
- if (root->d_covers == root)
+ if (mnt->mnt_parent == mnt)
count--;
if (count != 2)
return -EBUSY;
goto mount_it;
}
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
continue;
if (!try_inc_mod_count(fs_type->owner))
continue;
- spin_unlock(&file_systems_lock);
+ read_unlock(&file_systems_lock);
sb = read_super(ROOT_DEV,bdev,fs_type,root_mountflags,NULL,1);
if (sb)
goto mount_it;
- spin_lock(&file_systems_lock);
+ read_lock(&file_systems_lock);
put_filesystem(fs_type);
}
- spin_unlock(&file_systems_lock);
- panic("VFS: Unable to mount root fs on %s",
- kdevname(ROOT_DEV));
+ read_unlock(&file_systems_lock);
+ panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
mount_it:
printk ("VFS: Mounted root (%s filesystem)%s.\n",
mount_root();
#if 1
shrink_dcache();
- printk("change_root: old root has d_count=%d\n", old_root->d_count);
+ printk("change_root: old root has d_count=%d\n",
+ old_rootmnt->mnt_root->d_count);
#endif
mount_devfs_fs ();
/*
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
-extern void atomic_add(int a, atomic_t *v);
-extern int atomic_add_return(int a, atomic_t *v);
-extern void atomic_sub(int a, atomic_t *v);
-extern void atomic_inc(atomic_t *v);
-extern int atomic_inc_return(atomic_t *v);
-extern void atomic_dec(atomic_t *v);
-extern int atomic_dec_return(atomic_t *v);
-extern int atomic_dec_and_test(atomic_t *v);
-
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
-#if 0 /* for now */
-extern __inline__ void atomic_add(atomic_t a, atomic_t *v)
+extern __inline__ int atomic_add_return(int a, atomic_t *v)
{
- atomic_t t;
+ int t;
__asm__ __volatile__("\n\
1: lwarx %0,0,%3\n\
add %0,%2,%0\n\
stwcx. %0,0,%3\n\
- bne 1b"
+ bne- 1b"
: "=&r" (t), "=m" (*v)
- : "r" (a), "r" (v)
+ : "r" (a), "r" (v), "m" (*v)
: "cc");
-}
-extern __inline__ void atomic_sub(atomic_t a, atomic_t *v)
-{
- atomic_t t;
-
- __asm__ __volatile__("\n\
-1: lwarx %0,0,%3\n\
- subf %0,%2,%0\n\
- stwcx. %0,0,%3\n\
- bne 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (a), "r" (v)
- : "cc");
+ return t;
}
-extern __inline__ int atomic_sub_and_test(atomic_t a, atomic_t *v)
+extern __inline__ int atomic_sub_return(int a, atomic_t *v)
{
- atomic_t t;
+ int t;
__asm__ __volatile__("\n\
1: lwarx %0,0,%3\n\
subf %0,%2,%0\n\
stwcx. %0,0,%3\n\
- bne 1b"
+ bne- 1b"
: "=&r" (t), "=m" (*v)
- : "r" (a), "r" (v)
+ : "r" (a), "r" (v), "m" (*v)
: "cc");
- return t == 0;
+ return t;
}
-extern __inline__ void atomic_inc(atomic_t *v)
+extern __inline__ int atomic_inc_return(atomic_t *v)
{
- atomic_t t;
+ int t;
__asm__ __volatile__("\n\
1: lwarx %0,0,%2\n\
addic %0,%0,1\n\
stwcx. %0,0,%2\n\
- bne 1b"
+ bne- 1b"
: "=&r" (t), "=m" (*v)
- : "r" (v)
+ : "r" (v), "m" (*v)
: "cc");
-}
-
-extern __inline__ void atomic_dec(atomic_t *v)
-{
- atomic_t t;
- __asm__ __volatile__("\n\
-1: lwarx %0,0,%2\n\
- addic %0,%0,-1\n\
- stwcx. %0,0,%2\n\
- bne 1b"
- : "=&r" (t), "=m" (*v)
- : "r" (v)
- : "cc");
+ return t;
}
-extern __inline__ int atomic_dec_and_test(atomic_t *v)
+extern __inline__ int atomic_dec_return(atomic_t *v)
{
- atomic_t t;
+ int t;
__asm__ __volatile__("\n\
1: lwarx %0,0,%2\n\
stwcx. %0,0,%2\n\
bne 1b"
: "=&r" (t), "=m" (*v)
- : "r" (v)
+ : "r" (v), "m" (*v)
: "cc");
- return t == 0;
+ return t;
}
-#endif /* 0 */
+
+#define atomic_add(a, v) ((void) atomic_add_return((a), (v)))
+#define atomic_sub(a, v) ((void) atomic_sub_return((a), (v)))
+#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+#define atomic_inc(v) ((void) atomic_inc_return((v)))
+#define atomic_dec(v) ((void) atomic_dec_return((v)))
+#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
#endif /* _ASM_PPC_ATOMIC_H_ */
extern int test_and_clear_bit(int nr, volatile void *addr);
extern int test_and_change_bit(int nr, volatile void *addr);
-
-/* Returns the number of 0's to the left of the most significant 1 bit */
-extern __inline__ int cntlzw(int bits)
-{
- int lz;
-
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
- return lz;
-}
+/*
+ * Arguably these bit operations don't imply any memory barrier or
+ * SMP ordering, but in fact a lot of drivers expect them to imply
+ * both, since they do on x86 cpus.
+ */
+#ifdef CONFIG_SMP
+#define SMP_WMB "eieio\n"
+#define SMP_MB "\nsync"
+#else
+#define SMP_WMB
+#define SMP_MB
+#endif /* CONFIG_SMP */
/*
* These are if'd out here because using : "cc" as a constraint
return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0;
}
-extern __inline__ int ffz(unsigned int x)
+/* Return the bit position of the most significant 1 bit in a word */
+extern __inline__ int __ilog2(unsigned int x)
{
- int n;
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 31 - lz;
+}
- if (x == ~0)
+extern __inline__ int ffz(unsigned int x)
+{
+ if ((x = ~x) == 0)
return 32;
- x = ~x & (x+1); /* set LS zero to 1, other bits to 0 */
- __asm__ ("cntlzw %0,%1" : "=r" (n) : "r" (x));
- return 31 - n;
+ return __ilog2(x & -x);
}
#ifdef __KERNEL__
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-
-#define ffs(x) generic_ffs(x)
-
-#if 0
-/* untested, someone with PPC knowledge? */
-/* From Alexander Kjeldaas <astor@guardian.no> */
extern __inline__ int ffs(int x)
{
- int result;
- asm ("cntlzw %0,%1" : "=r" (result) : "r" (x));
- return 32 - result; /* IBM backwards ordering of bits */
+ return __ilog2(x & -x) + 1;
}
-#endif
/*
* hweightN: returns the hamming weight (i.e. the number
#include <asm/processor.h>
/* bytes per L1 cache line */
-#define L1_CACHE_BYTES 32
-#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-#define L1_CACHE_PAGES 8
+#if !defined(CONFIG_8xx) || defined(CONFIG_8260)
+#define L1_CACHE_BYTES 32
+#else
+#define L1_CACHE_BYTES 16
+#endif /* !8xx || 8260 */
+
+#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+#define L1_CACHE_PAGES 8
-#define SMP_CACHE_BYTES L1_CACHE_BYTES
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
#ifdef MODULE
#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
--- /dev/null
+
+/*
+ * MPC8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the MPC8260 internal
+ * memory map. See immap.h for details.
+ */
+#ifndef __CPM_82XX__
+#define __CPM_82XX__
+
+#include <asm/immap_8260.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST ((uint)0x80000000)
+#define CPM_CR_PAGE ((uint)0x7c000000)
+#define CPM_CR_SBLOCK ((uint)0x03e00000)
+#define CPM_CR_FLG ((uint)0x00010000)
+#define CPM_CR_MCN ((uint)0x00003fc0)
+#define CPM_CR_OPCODE ((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK (0x04)
+#define CPM_CR_SCC2_SBLOCK (0x05)
+#define CPM_CR_SCC3_SBLOCK (0x06)
+#define CPM_CR_SCC4_SBLOCK (0x07)
+#define CPM_CR_SMC1_SBLOCK (0x08)
+#define CPM_CR_SMC2_SBLOCK (0x09)
+#define CPM_CR_SPI_SBLOCK (0x0a)
+#define CPM_CR_I2C_SBLOCK (0x0b)
+#define CPM_CR_TIMER_SBLOCK (0x0f)
+#define CPM_CR_RAND_SBLOCK (0x0e)
+#define CPM_CR_FCC1_SBLOCK (0x10)
+#define CPM_CR_FCC2_SBLOCK (0x11)
+#define CPM_CR_FCC3_SBLOCK (0x12)
+#define CPM_CR_IDMA1_SBLOCK (0x14)
+#define CPM_CR_IDMA2_SBLOCK (0x15)
+#define CPM_CR_IDMA3_SBLOCK (0x16)
+#define CPM_CR_IDMA4_SBLOCK (0x17)
+#define CPM_CR_MCC1_SBLOCK (0x1c)
+
+#define CPM_CR_SCC1_PAGE (0x00)
+#define CPM_CR_SCC2_PAGE (0x01)
+#define CPM_CR_SCC3_PAGE (0x02)
+#define CPM_CR_SCC4_PAGE (0x03)
+#define CPM_CR_SMC1_PAGE (0x07)
+#define CPM_CR_SMC2_PAGE (0x08)
+#define CPM_CR_SPI_PAGE (0x09)
+#define CPM_CR_I2C_PAGE (0x0a)
+#define CPM_CR_TIMER_PAGE (0x0a)
+#define CPM_CR_RAND_PAGE (0x0a)
+#define CPM_CR_FCC1_PAGE (0x04)
+#define CPM_CR_FCC2_PAGE (0x05)
+#define CPM_CR_FCC3_PAGE (0x06)
+#define CPM_CR_IDMA1_PAGE (0x07)
+#define CPM_CR_IDMA2_PAGE (0x08)
+#define CPM_CR_IDMA3_PAGE (0x09)
+#define CPM_CR_IDMA4_PAGE (0x0a)
+#define CPM_CR_MCC1_PAGE (0x07)
+#define CPM_CR_MCC2_PAGE (0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX ((ushort)0x0000)
+#define CPM_CR_INIT_RX ((ushort)0x0001)
+#define CPM_CR_INIT_TX ((ushort)0x0002)
+#define CPM_CR_HUNT_MODE ((ushort)0x0003)
+#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_RESTART_TX ((ushort)0x0006)
+#define CPM_CR_SET_GADDR ((ushort)0x0008)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+ ((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses. The first 16K is available for almost
+ * any CPM use, so we put the BDs there. The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that. All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE ((uint)128)
+#define CPM_DATAONLY_SIZE ((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_DP_NOSPACE ((uint)0x7fffffff)
+
+/* The number of pages of host memory we allocate for CPM. This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES 2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern cpm8260_t *cpmp; /* Pointer to comm processor */
+uint m8260_cpm_dpalloc(uint size);
+uint m8260_cpm_hostalloc(uint size);
+void m8260_cpm_setbrg(uint brg, uint rate);
+void m8260_cpm_fastbrg(uint brg, uint rate, int div16);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+ ushort cbd_sc; /* Status and Control */
+ ushort cbd_datlen; /* Data length in buffer */
+ uint cbd_bufaddr; /* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */
+#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */
+#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */
+#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */
+#define BD_SC_LAST ((ushort)0x0800) /* Last buffer in frame */
+#define BD_SC_CM ((ushort)0x0200) /* Continous mode */
+#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */
+#define BD_SC_P ((ushort)0x0100) /* xmt preamble */
+#define BD_SC_BR ((ushort)0x0020) /* Break received */
+#define BD_SC_FR ((ushort)0x0010) /* Framing error */
+#define BD_SC_PR ((ushort)0x0008) /* Parity error */
+#define BD_SC_OV ((ushort)0x0002) /* Overrun */
+#define BD_SC_CD ((ushort)0x0001) /* ?? */
+
+/* Parameter RAM offsets from the base.
+*/
+#define PROFF_SCC1 ((uint)0x8000)
+#define PROFF_SCC2 ((uint)0x8100)
+#define PROFF_SCC3 ((uint)0x8200)
+#define PROFF_SCC4 ((uint)0x8300)
+#define PROFF_FCC1 ((uint)0x8400)
+#define PROFF_FCC2 ((uint)0x8500)
+#define PROFF_FCC3 ((uint)0x8600)
+#define PROFF_MCC1 ((uint)0x8700)
+#define PROFF_SMC1_BASE ((uint)0x87fc)
+#define PROFF_IDMA1_BASE ((uint)0x87fe)
+#define PROFF_MCC2 ((uint)0x8800)
+#define PROFF_SMC2_BASE ((uint)0x88fc)
+#define PROFF_IDMA2_BASE ((uint)0x88fe)
+#define PROFF_SPI_BASE ((uint)0x89fc)
+#define PROFF_IDMA3_BASE ((uint)0x89fe)
+#define PROFF_TIMERS ((uint)0x8ae0)
+#define PROFF_REVNUM ((uint)0x8af0)
+#define PROFF_RAND ((uint)0x8af8)
+#define PROFF_I2C_BASE ((uint)0x8afc)
+#define PROFF_IDMA4_BASE ((uint)0x89fe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1 (0)
+#define PROFF_SMC2 (64)
+
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+ ushort smc_rbase; /* Rx Buffer descriptor base address */
+ ushort smc_tbase; /* Tx Buffer descriptor base address */
+ u_char smc_rfcr; /* Rx function code */
+ u_char smc_tfcr; /* Tx function code */
+ ushort smc_mrblr; /* Max receive buffer length */
+ uint smc_rstate; /* Internal */
+ uint smc_idp; /* Internal */
+ ushort smc_rbptr; /* Internal */
+ ushort smc_ibc; /* Internal */
+ uint smc_rxtmp; /* Internal */
+ uint smc_tstate; /* Internal */
+ uint smc_tdp; /* Internal */
+ ushort smc_tbptr; /* Internal */
+ ushort smc_tbc; /* Internal */
+ uint smc_txtmp; /* Internal */
+ ushort smc_maxidl; /* Maximum idle characters */
+ ushort smc_tmpidl; /* Temporary idle counter */
+ ushort smc_brklen; /* Last received break length */
+ ushort smc_brkec; /* rcv'd break condition counter */
+ ushort smc_brkcr; /* xmt break count register */
+ ushort smc_rmask; /* Temporary bit mask */
+ uint smc_stmp; /* SDMA Temp */
+} smc_uart_t;
+
+/* Function code bits.
+*/
+#define SMC_GBL ((u_char)0x20) /* Set memory snooping */
+#define SMC_EB ((u_char)0x10) /* Set big endian byte order */
+#define SMC_TC2 ((u_char)0x04) /* Transfer code 2 value */
+#define SMC_DTB ((u_char)0x02) /* Use local bus when set */
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define SMCMR_REN ((ushort)0x0001)
+#define SMCMR_TEN ((ushort)0x0002)
+#define SMCMR_DM ((ushort)0x000c)
+#define SMCMR_SM_GCI ((ushort)0x0000)
+#define SMCMR_SM_UART ((ushort)0x0020)
+#define SMCMR_SM_TRANS ((ushort)0x0030)
+#define SMCMR_SM_MASK ((ushort)0x0030)
+#define SMCMR_PM_EVEN ((ushort)0x0100) /* Even parity, else odd */
+#define SMCMR_REVD SMCMR_PM_EVEN
+#define SMCMR_PEN ((ushort)0x0200) /* Parity enable */
+#define SMCMR_BS SMCMR_PEN
+#define SMCMR_SL ((ushort)0x0400) /* Two stops, else one */
+#define SMCR_CLEN_MASK ((ushort)0x7800) /* Character length */
+#define smcr_mk_clen(C) (((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define SMCM_TXE ((unsigned char)0x10)
+#define SMCM_BSY ((unsigned char)0x04)
+#define SMCM_TX ((unsigned char)0x02)
+#define SMCM_RX ((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST ((uint)0x00020000)
+#define CPM_BRG_EN ((uint)0x00010000)
+#define CPM_BRG_EXTC_INT ((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
+#define CPM_BRG_ATB ((uint)0x00002000)
+#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
+#define CPM_BRG_DIV16 ((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP ((uint)0x00040000)
+#define SCC_GSMRH_GDE ((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT ((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC ((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC ((uint)0x00000000)
+#define SCC_GSMRH_REVD ((uint)0x00002000)
+#define SCC_GSMRH_TRX ((uint)0x00001000)
+#define SCC_GSMRH_TTX ((uint)0x00000800)
+#define SCC_GSMRH_CDP ((uint)0x00000400)
+#define SCC_GSMRH_CTSP ((uint)0x00000200)
+#define SCC_GSMRH_CDS ((uint)0x00000100)
+#define SCC_GSMRH_CTSS ((uint)0x00000080)
+#define SCC_GSMRH_TFL ((uint)0x00000040)
+#define SCC_GSMRH_RFW ((uint)0x00000020)
+#define SCC_GSMRH_TXSY ((uint)0x00000010)
+#define SCC_GSMRH_SYNL16 ((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8 ((uint)0x00000008)
+#define SCC_GSMRH_SYNL4 ((uint)0x00000004)
+#define SCC_GSMRH_RTSM ((uint)0x00000002)
+#define SCC_GSMRH_RSYN ((uint)0x00000001)
+
+#define SCC_GSMRL_SIR ((uint)0x80000000) /* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE ((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG ((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS ((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH ((uint)0x00000000)
+#define SCC_GSMRL_TCI ((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3 ((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4 ((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14 ((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF ((uint)0x00000000)
+#define SCC_GSMRL_RINV ((uint)0x02000000)
+#define SCC_GSMRL_TINV ((uint)0x01000000)
+#define SCC_GSMRL_TPL_128 ((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64 ((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48 ((uint)0x00800000)
+#define SCC_GSMRL_TPL_32 ((uint)0x00600000)
+#define SCC_GSMRL_TPL_16 ((uint)0x00400000)
+#define SCC_GSMRL_TPL_8 ((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE ((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1 ((uint)0x00180000)
+#define SCC_GSMRL_TPP_01 ((uint)0x00100000)
+#define SCC_GSMRL_TPP_10 ((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS ((uint)0x00000000)
+#define SCC_GSMRL_TEND ((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32 ((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16 ((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8 ((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32 ((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16 ((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8 ((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN ((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH ((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0 ((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI ((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN ((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH ((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0 ((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI ((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE ((uint)0x000000c0) /* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO ((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP ((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM ((uint)0x00000000)
+#define SCC_GSMRL_ENR ((uint)0x00000020)
+#define SCC_GSMRL_ENT ((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET ((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP ((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC ((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14 ((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC ((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS ((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART ((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7 ((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK ((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC ((uint)0x00000000)
+
+#define SCC_TODR_TOD ((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE ((unsigned char)0x10)
+#define SCCM_BSY ((unsigned char)0x04)
+#define SCCM_TX ((unsigned char)0x02)
+#define SCCM_RX ((unsigned char)0x01)
+
+typedef struct scc_param {
+ ushort scc_rbase; /* Rx Buffer descriptor base address */
+ ushort scc_tbase; /* Tx Buffer descriptor base address */
+ u_char scc_rfcr; /* Rx function code */
+ u_char scc_tfcr; /* Tx function code */
+ ushort scc_mrblr; /* Max receive buffer length */
+ uint scc_rstate; /* Internal */
+ uint scc_idp; /* Internal */
+ ushort scc_rbptr; /* Internal */
+ ushort scc_ibc; /* Internal */
+ uint scc_rxtmp; /* Internal */
+ uint scc_tstate; /* Internal */
+ uint scc_tdp; /* Internal */
+ ushort scc_tbptr; /* Internal */
+ ushort scc_tbc; /* Internal */
+ uint scc_txtmp; /* Internal */
+ uint scc_rcrc; /* Internal */
+ uint scc_tcrc; /* Internal */
+} sccp_t;
+
+/* Function code bits.
+*/
+#define SCC_EB ((u_char)0x10) /* Set big endian byte order */
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+ sccp_t sen_genscc;
+ uint sen_cpres; /* Preset CRC */
+ uint sen_cmask; /* Constant mask for CRC */
+ uint sen_crcec; /* CRC Error counter */
+ uint sen_alec; /* alignment error counter */
+ uint sen_disfc; /* discard frame counter */
+ ushort sen_pads; /* Tx short frame pad character */
+ ushort sen_retlim; /* Retry limit threshold */
+ ushort sen_retcnt; /* Retry limit counter */
+ ushort sen_maxflr; /* maximum frame length register */
+ ushort sen_minflr; /* minimum frame length register */
+ ushort sen_maxd1; /* maximum DMA1 length */
+ ushort sen_maxd2; /* maximum DMA2 length */
+ ushort sen_maxd; /* Rx max DMA */
+ ushort sen_dmacnt; /* Rx DMA counter */
+ ushort sen_maxb; /* Max BD byte count */
+ ushort sen_gaddr1; /* Group address filter */
+ ushort sen_gaddr2;
+ ushort sen_gaddr3;
+ ushort sen_gaddr4;
+ uint sen_tbuf0data0; /* Save area 0 - current frame */
+ uint sen_tbuf0data1; /* Save area 1 - current frame */
+ uint sen_tbuf0rba; /* Internal */
+ uint sen_tbuf0crc; /* Internal */
+ ushort sen_tbuf0bcnt; /* Internal */
+ ushort sen_paddrh; /* physical address (MSB) */
+ ushort sen_paddrm;
+ ushort sen_paddrl; /* physical address (LSB) */
+ ushort sen_pper; /* persistence */
+ ushort sen_rfbdptr; /* Rx first BD pointer */
+ ushort sen_tfbdptr; /* Tx first BD pointer */
+ ushort sen_tlbdptr; /* Tx last BD pointer */
+ uint sen_tbuf1data0; /* Save area 0 - current frame */
+ uint sen_tbuf1data1; /* Save area 1 - current frame */
+ uint sen_tbuf1rba; /* Internal */
+ uint sen_tbuf1crc; /* Internal */
+ ushort sen_tbuf1bcnt; /* Internal */
+ ushort sen_txlen; /* Tx Frame length counter */
+ ushort sen_iaddr1; /* Individual address filter */
+ ushort sen_iaddr2;
+ ushort sen_iaddr3;
+ ushort sen_iaddr4;
+ ushort sen_boffcnt; /* Backoff counter */
+
+ /* NOTE: Some versions of the manual have the following items
+ * incorrectly documented. Below is the proper order.
+ */
+ ushort sen_taddrh; /* temp address (MSB) */
+ ushort sen_taddrm;
+ ushort sen_taddrl; /* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
+#define SCCE_ENET_TXE ((ushort)0x0010) /* Transmit Error */
+#define SCCE_ENET_RXF ((ushort)0x0008) /* Full frame received */
+#define SCCE_ENET_BSY ((ushort)0x0004) /* All incoming buffers full */
+#define SCCE_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
+#define SCCE_ENET_RXB ((ushort)0x0001) /* A buffer was received */
+
+/* SCC Mode Register (PMSR) as used by Ethernet.
+*/
+#define SCC_PMSR_HBC ((ushort)0x8000) /* Enable heartbeat */
+#define SCC_PMSR_FC ((ushort)0x4000) /* Force collision */
+#define SCC_PMSR_RSH ((ushort)0x2000) /* Receive short frames */
+#define SCC_PMSR_IAM ((ushort)0x1000) /* Check individual hash */
+#define SCC_PMSR_ENCRC ((ushort)0x0800) /* Ethernet CRC mode */
+#define SCC_PMSR_PRO ((ushort)0x0200) /* Promiscuous mode */
+#define SCC_PMSR_BRO ((ushort)0x0100) /* Catch broadcast pkts */
+#define SCC_PMSR_SBT ((ushort)0x0080) /* Special backoff timer */
+#define SCC_PMSR_LPB ((ushort)0x0040) /* Set Loopback mode */
+#define SCC_PMSR_SIP ((ushort)0x0020) /* Sample Input Pins */
+#define SCC_PMSR_LCW ((ushort)0x0010) /* Late collision window */
+#define SCC_PMSR_NIB22 ((ushort)0x000a) /* Start frame search */
+#define SCC_PMSR_FDE ((ushort)0x0001) /* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+*/
+#define BD_ENET_RX_EMPTY ((ushort)0x8000)
+#define BD_ENET_RX_WRAP ((ushort)0x2000)
+#define BD_ENET_RX_INTR ((ushort)0x1000)
+#define BD_ENET_RX_LAST ((ushort)0x0800)
+#define BD_ENET_RX_FIRST ((ushort)0x0400)
+#define BD_ENET_RX_MISS ((ushort)0x0100)
+#define BD_ENET_RX_LG ((ushort)0x0020)
+#define BD_ENET_RX_NO ((ushort)0x0010)
+#define BD_ENET_RX_SH ((ushort)0x0008)
+#define BD_ENET_RX_CR ((ushort)0x0004)
+#define BD_ENET_RX_OV ((ushort)0x0002)
+#define BD_ENET_RX_CL ((ushort)0x0001)
+#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+*/
+#define BD_ENET_TX_READY ((ushort)0x8000)
+#define BD_ENET_TX_PAD ((ushort)0x4000)
+#define BD_ENET_TX_WRAP ((ushort)0x2000)
+#define BD_ENET_TX_INTR ((ushort)0x1000)
+#define BD_ENET_TX_LAST ((ushort)0x0800)
+#define BD_ENET_TX_TC ((ushort)0x0400)
+#define BD_ENET_TX_DEF ((ushort)0x0200)
+#define BD_ENET_TX_HB ((ushort)0x0100)
+#define BD_ENET_TX_LC ((ushort)0x0080)
+#define BD_ENET_TX_RL ((ushort)0x0040)
+#define BD_ENET_TX_RCMASK ((ushort)0x003c)
+#define BD_ENET_TX_UN ((ushort)0x0002)
+#define BD_ENET_TX_CSL ((ushort)0x0001)
+#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+ sccp_t scc_genscc;
+ uint scc_res1; /* Reserved */
+ uint scc_res2; /* Reserved */
+ ushort scc_maxidl; /* Maximum idle chars */
+ ushort scc_idlc; /* temp idle counter */
+ ushort scc_brkcr; /* Break count register */
+ ushort scc_parec; /* receive parity error counter */
+ ushort scc_frmec; /* receive framing error counter */
+ ushort scc_nosec; /* receive noise counter */
+ ushort scc_brkec; /* receive break condition counter */
+ ushort scc_brkln; /* last received break length */
+ ushort scc_uaddr1; /* UART address character 1 */
+ ushort scc_uaddr2; /* UART address character 2 */
+ ushort scc_rtemp; /* Temp storage */
+ ushort scc_toseq; /* Transmit out of sequence char */
+ ushort scc_char1; /* control character 1 */
+ ushort scc_char2; /* control character 2 */
+ ushort scc_char3; /* control character 3 */
+ ushort scc_char4; /* control character 4 */
+ ushort scc_char5; /* control character 5 */
+ ushort scc_char6; /* control character 6 */
+ ushort scc_char7; /* control character 7 */
+ ushort scc_char8; /* control character 8 */
+ ushort scc_rccm; /* receive control character mask */
+ ushort scc_rccr; /* receive control character register */
+ ushort scc_rlbc; /* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR ((ushort)0x1000)
+#define UART_SCCM_GLT ((ushort)0x0800)
+#define UART_SCCM_AB ((ushort)0x0200)
+#define UART_SCCM_IDL ((ushort)0x0100)
+#define UART_SCCM_GRA ((ushort)0x0080)
+#define UART_SCCM_BRKE ((ushort)0x0040)
+#define UART_SCCM_BRKS ((ushort)0x0020)
+#define UART_SCCM_CCR ((ushort)0x0008)
+#define UART_SCCM_BSY ((ushort)0x0004)
+#define UART_SCCM_TX ((ushort)0x0002)
+#define UART_SCCM_RX ((ushort)0x0001)
+
+/* The SCC PMSR when used as a UART.
+*/
+#define SCU_PMSR_FLC ((ushort)0x8000)
+#define SCU_PMSR_SL ((ushort)0x4000)
+#define SCU_PMSR_CL ((ushort)0x3000)
+#define SCU_PMSR_UM ((ushort)0x0c00)
+#define SCU_PMSR_FRZ ((ushort)0x0200)
+#define SCU_PMSR_RZS ((ushort)0x0100)
+#define SCU_PMSR_SYN ((ushort)0x0080)
+#define SCU_PMSR_DRT ((ushort)0x0040)
+#define SCU_PMSR_PEN ((ushort)0x0010)
+#define SCU_PMSR_RPM ((ushort)0x000c)
+#define SCU_PMSR_REVP ((ushort)0x0008)
+#define SCU_PMSR_TPM ((ushort)0x0003)
+#define SCU_PMSR_TEVP ((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+ sccp_t st_genscc;
+ uint st_cpres; /* Preset CRC */
+ uint st_cmask; /* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST ((ushort)0x0800)
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+ ushort iic_rbase; /* Rx Buffer descriptor base address */
+ ushort iic_tbase; /* Tx Buffer descriptor base address */
+ u_char iic_rfcr; /* Rx function code */
+ u_char iic_tfcr; /* Tx function code */
+ ushort iic_mrblr; /* Max receive buffer length */
+ uint iic_rstate; /* Internal */
+ uint iic_rdp; /* Internal */
+ ushort iic_rbptr; /* Internal */
+ ushort iic_rbc; /* Internal */
+ uint iic_rxtmp; /* Internal */
+ uint iic_tstate; /* Internal */
+ uint iic_tdp; /* Internal */
+ ushort iic_tbptr; /* Internal */
+ ushort iic_tbc; /* Internal */
+ uint iic_txtmp; /* Internal */
+} iic_t;
+
+#define BD_IIC_START ((ushort)0x0400)
+
+#endif /* __CPM_82XX__ */
--- /dev/null
+
+#define IMAP_ADDR ((uint)0xf0000000)
+
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+ unsigned int bi_memstart; /* Memory start address */
+ unsigned int bi_memsize; /* Memory (end) size in bytes */
+ unsigned int bi_intfreq; /* Internal Freq, in Hz */
+ unsigned int bi_busfreq; /* Bus Freq, in MHz */
+ unsigned int bi_cpmfreq; /* CPM Freq, in MHz */
+ unsigned int bi_brgfreq; /* BRG Freq, in MHz */
+ unsigned char bi_enetaddr[6];
+ unsigned int bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
FEATURE_Mediabay_reset,
FEATURE_Mediabay_power,
FEATURE_Mediabay_PCI_enable,
- FEATURE_Mediabay_IDE_enable, /* Also IDE 1 */
- FEATURE_Mediabay_IDE_reset, /* Also IDE 1 */
+ FEATURE_IDE1_enable, /* MediaBay IDE */
+ FEATURE_IDE1_reset, /* MediaBay IDE */
FEATURE_Mediabay_floppy_enable,
FEATURE_BMac_reset,
FEATURE_BMac_IO_enable,
FEATURE_Sound_CLK_enable,
FEATURE_IDE2_enable,
FEATURE_IDE2_reset,
+ FEATURE_Mediabay_IDE_switch, /* MB IDE bus switch */
+ FEATURE_Mediabay_content, /* MB content indicator enable */
FEATURE_last,
};
#define BASE_BAUD (24576000 / 16)
#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (/*ASYNC_BOOT_AUTOCONF|*/ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
#else
-#define STD_COM_FLAGS (/*ASYNC_BOOT_AUTOCONF|*/ASYNC_SKIP_TEST)
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
#endif
* Bits in feature control register.
* Bits postfixed with a _N are in inverse logic
*/
-#define HRW_RESET_SCC 1 /* Named in_use_led in OF ??? */
+#define HRW_MODEM_POWER_N 1 /* turns off modem power */
#define HRW_BAY_POWER_N 2
#define HRW_BAY_PCI_ENABLE 4
#define HRW_BAY_IDE_ENABLE 8
#define HRW_ARB_BYPASS 0x400000 /* ??? (0 on main, 1 on gatwick) */
#define HRW_IDE1_RESET_N 0x800000 /* Media bay */
#define HRW_SLOW_SCC_PCLK 0x1000000 /* ??? (0) */
-#define HRW_MODEM_POWER_N 0x2000000 /* Used by internal modem on wallstreet */
+#define HRW_RESET_SCC 0x2000000 /* perhaps? */
#define HRW_MFDC_CELL_ENABLE 0x4000000 /* ??? (0) */
#define HRW_USE_MFDC 0x8000000 /* ??? (0) */
#define HRW_BMAC_IO_ENABLE 0x60000000 /* two bits, not documented in OF */
#define HRW_BMAC_RESET 0x80000000 /* not documented in OF */
+
+
+#define PADD_MODEM_POWER_N 0x00000001 /* modem power on paddington */
void ide_outsw(ide_ioreg_t port, void *buf, int ns);
void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
+#if 0
#undef insw
#define insw(port, buf, ns) do { \
ppc_ide_md.insw((port), (buf), (ns)); \
#define outsw(port, buf, ns) do { \
ppc_ide_md.outsw((port), (buf), (ns)); \
} while (0)
+#endif
#undef SUPPORT_SLOW_DATA_PORTS
#define SUPPORT_SLOW_DATA_PORTS 0
--- /dev/null
+
+/*
+ * MPC8260 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map of the 8260. I don't know how generic
+ * this will be, as I don't have any knowledge of the subsequent
+ * parts at this time. I copied this from the 8xx_immap.h.
+ */
+#ifndef __IMMAP_82XX__
+#define __IMMAP_82XX__
+
+/* System configuration registers.
+*/
+typedef struct sys_conf {
+ uint sc_siumcr;
+ uint sc_sypcr;
+ char res1[6];
+ ushort sc_swsr;
+ char res2[20];
+ uint sc_bcr;
+ u_char sc_ppc_acr;
+ char res3[3];
+ uint sc_ppc_alrh;
+ uint sc_ppc_alrl;
+ u_char sc_lcl_acr;
+ char res4[3];
+ uint sc_lcl_alrh;
+ uint sc_lcl_alrl;
+ uint sc_tescr1;
+ uint sc_tescr2;
+ uint sc_ltescr1;
+ uint sc_ltescr2;
+ uint sc_pdtea;
+ u_char sc_pdtem;
+ char res5[3];
+ uint sc_ldtea;
+ u_char sc_ldtem;
+ char res6[163];
+} sysconf8260_t;
+
+
+/* Memory controller registers.
+*/
+typedef struct mem_ctlr {
+ uint memc_br0;
+ uint memc_or0;
+ uint memc_br1;
+ uint memc_or1;
+ uint memc_br2;
+ uint memc_or2;
+ uint memc_br3;
+ uint memc_or3;
+ uint memc_br4;
+ uint memc_or4;
+ uint memc_br5;
+ uint memc_or5;
+ uint memc_br6;
+ uint memc_or6;
+ uint memc_br7;
+ uint memc_or7;
+ uint memc_br8;
+ uint memc_or8;
+ uint memc_br9;
+ uint memc_or9;
+ uint memc_br10;
+ uint memc_or10;
+ uint memc_br11;
+ uint memc_or11;
+ char res1[8];
+ uint memc_mar;
+ char res2[4];
+ uint memc_mamr;
+ uint memc_mbmr;
+ uint memc_mcmr;
+ char res3[8];
+ ushort memc_mptpr;
+ char res4[2];
+ uint memc_mdr;
+ char res5[4];
+ uint memc_psdmr;
+ uint memc_lsdmr;
+ u_char memc_purt;
+ char res6[3];
+ u_char memc_psrt;
+ char res7[3];
+ u_char memc_lurt;
+ char res8[3];
+ u_char memc_lsrt;
+ char res9[3];
+ uint memc_immr;
+ char res10[84];
+} memctl8260_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+ char res1[32];
+ ushort sit_tmcntsc;
+ char res2[2];
+ uint sit_tmcnt;
+ char res3[4];
+ uint sit_tmcntal;
+ char res4[16];
+ ushort sit_piscr;
+ char res5[2];
+ uint sit_pitc;
+ uint sit_pitr;
+ char res6[94];
+ char res7[2390];
+} sit8260_t;
+
+#define PISCR_PIRQ_MASK ((ushort)0xff00)
+#define PISCR_PS ((ushort)0x0080)
+#define PISCR_PIE ((ushort)0x0004)
+#define PISCR_PTF ((ushort)0x0002)
+#define PISCR_PTE ((ushort)0x0001)
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+ ushort ic_sicr;
+ char res1[2];
+ uint ic_sivec;
+ uint ic_sipnrh;
+ uint ic_sipnrl;
+ uint ic_siprr;
+ uint ic_scprrh;
+ uint ic_scprrl;
+ uint ic_simrh;
+ uint ic_simrl;
+ uint ic_siexr;
+ char res2[88];
+} intctl8260_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+ uint car_sccr;
+ char res1[4];
+ uint car_scmr;
+ char res2[4];
+ uint car_rsr;
+ uint car_rmr;
+ char res[104];
+} car8260_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+ uint iop_pdira;
+ uint iop_ppara;
+ uint iop_psora;
+ uint iop_podra;
+ uint iop_pdata;
+ char res1[12];
+ uint iop_pdirb;
+ uint iop_pparb;
+ uint iop_psorb;
+ uint iop_podrb;
+ uint iop_pdatb;
+ char res2[12];
+ uint iop_pdirc;
+ uint iop_pparc;
+ uint iop_psorc;
+ uint iop_podrc;
+ uint iop_pdatc;
+ char res3[12];
+ uint iop_pdird;
+ uint iop_ppard;
+ uint iop_psord;
+ uint iop_podrd;
+ uint iop_pdatd;
+ char res4[12];
+} iop8260_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+ u_char cpmt_tgcr1;
+ char res1[3];
+ u_char cpmt_tgcr2;
+ char res2[11];
+ ushort cpmt_tmr1;
+ ushort cpmt_tmr2;
+ ushort cpmt_trr1;
+ ushort cpmt_trr2;
+ ushort cpmt_tcr1;
+ ushort cpmt_tcr2;
+ ushort cpmt_tcn1;
+ ushort cpmt_tcn2;
+ ushort cpmt_tmr3;
+ ushort cpmt_tmr4;
+ ushort cpmt_trr3;
+ ushort cpmt_trr4;
+ ushort cpmt_tcr3;
+ ushort cpmt_tcr4;
+ ushort cpmt_tcn3;
+ ushort cpmt_tcn4;
+ ushort cpmt_ter1;
+ ushort cpmt_ter2;
+ ushort cpmt_ter3;
+ ushort cpmt_ter4;
+ char res3[584];
+} cpmtimer8260_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+ char res0[24];
+ u_char sdma_sdsr;
+ char res1[3];
+ u_char sdma_sdmr;
+ char res2[3];
+ u_char sdma_idsr1;
+ char res3[3];
+ u_char sdma_idmr1;
+ char res4[3];
+ u_char sdma_idsr2;
+ char res5[3];
+ u_char sdma_idmr2;
+ char res6[3];
+ u_char sdma_idsr3;
+ char res7[3];
+ u_char sdma_idmr3;
+ char res8[3];
+ u_char sdma_idsr4;
+ char res9[3];
+ u_char sdma_idmr4;
+ char res10[707];
+} sdma8260_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+ uint fcc_gfmr;
+ uint fcc_fpsmr;
+ ushort fcc_ftodr;
+ char res1[2];
+ ushort fcc_fdsr;
+ char res2[2];
+ uint fcc_fcce;
+ uint fcc_fccm;
+ u_char fcc_fccs;
+ char res3[3];
+ u_char fcc_ftirr_phy[4];
+} fcc_t;
+
+/* I2C
+*/
+typedef struct i2c {
+ u_char i2c_i2mod;
+ char res1[3];
+ u_char i2c_i2add;
+ char res2[3];
+ u_char i2c_i2brg;
+ char res3[3];
+ u_char i2c_i2com;
+ char res4[3];
+ u_char i2c_i2cer;
+ char res5[3];
+ u_char i2c_i2cmr;
+ char res6[331];
+} i2c8260_t;
+
+typedef struct scc { /* Serial communication channels */
+ uint scc_gsmrl;
+ uint scc_gsmrh;
+ ushort scc_pmsr;
+ char res1[2];
+ ushort scc_todr;
+ ushort scc_dsr;
+ ushort scc_scce;
+ char res2[2];
+ ushort scc_sccm;
+ char res3;
+ u_char scc_sccs;
+ char res4[8];
+} scc_t;
+
+typedef struct smc { /* Serial management channels */
+ char res1[2];
+ ushort smc_smcmr;
+ char res2[2];
+ u_char smc_smce;
+ char res3[3];
+ u_char smc_smcm;
+ char res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct spi {
+ ushort spi_spmode;
+ char res1[4];
+ u_char spi_spie;
+ char res2[3];
+ u_char spi_spim;
+ char res3[2];
+ u_char spi_spcom;
+ char res4[82];
+} spi_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+ u_char cmx_si1cr;
+ char res1;
+ u_char cmx_si2cr;
+ char res2;
+ uint cmx_fcr;
+ uint cmx_scr;
+ u_char cmx_smr;
+ char res3;
+ ushort cmx_uar;
+ char res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+ ushort si_amr;
+ ushort si_bmr;
+ ushort si_cmr;
+ ushort si_dmr;
+ u_char si_gmr;
+ char res1;
+ u_char si_cmdr;
+ char res2;
+ u_char si_str;
+ char res3;
+ ushort si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+ ushort mcc_mcce;
+ char res1[2];
+ ushort mcc_mccm;
+ char res2[2];
+ u_char mcc_mccf;
+ char res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+ uint cp_cpcr;
+ uint cp_rccr;
+ char res1[14];
+ ushort cp_rter;
+ char res2[2];
+ ushort cp_rtmr;
+ ushort cp_rtscr;
+ char res3[2];
+ uint cp_rtsr;
+ char res4[12];
+} cpm8260_t;
+
+/* ...and the whole thing wrapped up....
+*/
+typedef struct immap {
+ /* Some references are into the unique and known dpram spaces,
+ * others are from the generic base.
+ */
+#define im_dprambase im_dpram1
+ u_char im_dpram1[16*1024];
+ char res1[16*1024];
+ u_char im_dpram2[4*1024];
+ char res2[8*1024];
+ u_char im_dpram3[4*1024];
+ char res3[16*1024];
+
+ sysconf8260_t im_siu_conf; /* SIU Configuration */
+ memctl8260_t im_memctl; /* Memory Controller */
+ sit8260_t im_sit; /* System Integration Timers */
+ intctl8260_t im_intctl; /* Interrupt Controller */
+ car8260_t im_clkrst; /* Clocks and reset */
+ iop8260_t im_ioport; /* IO Port control/status */
+ cpmtimer8260_t im_cpmtimer; /* CPM timers */
+ sdma8260_t im_sdma; /* SDMA control/status */
+
+ fcc_t im_fcc[3]; /* Three FCCs */
+
+ char res4[159];
+
+ /* First set of baud rate generators.
+ */
+ char res4a[496];
+ uint im_brgc5;
+ uint im_brgc6;
+ uint im_brgc7;
+ uint im_brgc8;
+
+ char res5[608];
+
+ i2c8260_t im_i2c; /* I2C control/status */
+ cpm8260_t im_cpm; /* Communication processor */
+
+ /* Second set of baud rate generators.
+ */
+ uint im_brgc1;
+ uint im_brgc2;
+ uint im_brgc3;
+ uint im_brgc4;
+
+ scc_t im_scc[4]; /* Four SCCs */
+ smc_t im_smc[2]; /* Couple of SMCs */
+ spi_t im_spi; /* A SPI */
+ cpmux_t im_cpmux; /* CPM clock route mux */
+ siramctl_t im_siramctl1; /* First SI RAM Control */
+ mcc_t im_mcc1; /* First MCC */
+ siramctl_t im_siramctl2; /* Second SI RAM Control */
+ mcc_t im_mcc2; /* Second MCC */
+
+ char res6[1184];
+
+ ushort im_si1txram[256];
+ char res7[512];
+ ushort im_si1rxram[256];
+ char res8[512];
+ ushort im_si2txram[256];
+ char res9[512];
+ ushort im_si2rxram[256];
+ char res10[512];
+ char res11[4096];
+} immap_t;
+
+/* The 8260 relies heavily on the IMMR, so we keep it around as a
+ * kernel global symbol now. Should have done this for the 8xx......
+ */
+immap_t *immr;
+
+#endif /* __IMMAP_82XX__ */
#include <asm/board.h>
#elif defined(CONFIG_8xx)
#include <asm/mpc8xx.h>
+#elif defined(CONFIG_8260)
+#include <asm/mpc8260.h>
#else
#ifdef CONFIG_APUS
#define _IO_BASE 0
#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
#endif
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
-#define insw(port, buf, ns) _insw((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define outsw(port, buf, ns) _outsw((u16 *)((port)+_IO_BASE), (buf), (ns))
-#define insl(port, buf, nl) _insl((u32 *)((port)+_IO_BASE), (buf), (nl))
-#define outsl(port, buf, nl) _outsl((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
#define inb(port) in_8((u8 *)((port)+_IO_BASE))
#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
extern void _outsw(volatile u16 *port, const void *buf, int ns);
extern void _insl(volatile u32 *port, void *buf, int nl);
extern void _outsl(volatile u32 *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
/*
* The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
*/
#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
-extern void _insw_ns(volatile u16 *port, void *buf, int ns);
-extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
-extern void _insl_ns(volatile u32 *port, void *buf, int nl);
-extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
#define IO_SPACE_LIMIT ~0
* There are eight external interrupts (IRQs) that can be configured
* as either level or edge sensitive.
*
- * The 82xx can have up to 64 interrupts on the internal controller.
- *
* On some implementations, there is also the possibility of an 8259
* through the PCI and PCI-ISA bridges.
*/
-#ifdef CONFIG_82xx
-#define NR_SIU_INTS 64
-#else
#define NR_SIU_INTS 16
-#endif
#define NR_IRQS (NR_SIU_INTS + NR_8259_INTS)
/* These values must be zero-based and map 1:1 with the SIU configuration.
- * They are used throughout the 8xx/82xx I/O subsystem to generate
+ * They are used throughout the 8xx I/O subsystem to generate
* interrupt masks, flags, and other control patterns. This is why the
* current kernel assumption of the 8259 as the base controller is such
* a pain in the butt.
*/
#define NR_IRQS 256
+#ifndef CONFIG_8260
+
#define NUM_8259_INTERRUPTS 16
#define IRQ_8259_CASCADE 16
#define openpic_to_irq(n) ((n)+NUM_8259_INTERRUPTS)
#define irq_to_openpic(n) ((n)-NUM_8259_INTERRUPTS)
+#else /* CONFIG_8260 */
+
+/* The 8260 has an internal interrupt controller with a maximum of
+ * 64 IRQs. We will use NR_IRQs from above since it is large enough.
+ * Don't be confused by the 8260 documentation where they list an
+ * "interrupt number" and "interrupt vector". We are only interested
+ * in the interrupt vector. There are "reserved" holes where the
+ * vector number increases, but the interrupt number in the table does not.
+ * (Document errata updates have fixed this...make sure you have up to
+ * date processor documentation -- Dan).
+ */
+#define NR_SIU_INTS 64
+
+/* There are many more than these, we will add them as we need them.
+*/
+#define SIU_INT_SMC1 ((uint)0x04)
+#define SIU_INT_SMC2 ((uint)0x05)
+#define SIU_INT_SCC1 ((uint)0x28)
+#define SIU_INT_SCC2 ((uint)0x29)
+#define SIU_INT_SCC3 ((uint)0x2a)
+#define SIU_INT_SCC4 ((uint)0x2b)
+
+#endif /* CONFIG_8260 */
+
/*
* This gets called from serial.c, which is now used on
* powermacs as well as prep/chrp boxes.
--- /dev/null
+
+/* This is the single file included by all MPC8260 build options.
+ * Since there are many different boards and no standard configuration,
+ * we have a unique include file for each. Rather than change every
+ * file that has to include MPC8260 configuration, they all include
+ * this one and the configuration switching is done here.
+ */
+#ifndef __CONFIG_8260_DEFS
+#define __CONFIG_8260_DEFS
+
+#ifdef CONFIG_8260
+
+#ifdef CONFIG_EST8260
+#include <asm/est8260.h>
+#endif
+
+/* I don't yet have the ISA or PCI stuff done....no 8260 with
+ * such thing.....
+ */
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+
+/* The "residual" data board information structure the boot loader
+ * hands to us.
+ */
+extern unsigned char __res[];
+
+/* I need this to get pt_regs.......
+*/
+#include <asm/ptrace.h>
+
+extern int request_8xxirq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags,
+ const char *device,
+ void *dev_id);
+
+#endif /* CONFIG_8260 */
+#endif
#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
#endif
+/* PowerMac specific nvram stuffs */
+
+enum {
+ pmac_nvram_OF, /* Open Firmware partition */
+ pmac_nvram_XPRAM, /* MacOS XPRAM partition */
+ pmac_nvram_NR /* MacOS Name Registry partition */
+};
+
+/* Return partition offset in nvram */
+extern int pmac_get_partition(int partition);
+
+/* Direct access to XPRAM */
+extern u8 pmac_xpram_read(int xpaddr);
+extern void pmac_xpram_write(int xpaddr, u8 data);
+
+/* Some offsets in XPRAM */
+#define PMAC_XPRAM_MACHINE_LOC 0xe4
+#define PMAC_XPRAM_SOUND_VOLUME 0x08
+
+/* Machine location structure in XPRAM */
+struct pmac_machine_location {
+ u32 latitude; /* 2+30 bit Fractional number */
+ u32 longitude; /* 2+30 bit Fractional number */
+ u32 delta; /* mix of GMT delta and DLS */
+};
+
#endif
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(mm, a, b) do { } while (0)
#define flush_cache_page(vma, p) do { } while (0)
+#define flush_icache_page(vma, page) do { } while (0)
extern void flush_icache_range(unsigned long, unsigned long);
extern void __flush_page_to_ram(unsigned long page_va);
#define flush_page_to_ram(page) __flush_page_to_ram(page_address(page))
-extern void __flush_icache_page(unsigned long page_va);
-#define flush_icache_page(vma, page) __flush_icache_page(page_address(page))
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(struct task_struct *tsk, unsigned long address);
#define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */
#define _PAGE_SHARED 0x0004 /* No ASID (context) compare */
-/* These four software bits must be masked out when the entry is loaded
+/* These five software bits must be masked out when the entry is loaded
* into the TLB.
*/
+#define _PAGE_DIRTY 0x0008 /* software: page changed */
#define _PAGE_GUARDED 0x0010 /* software: guarded access */
#define _PAGE_WRITETHRU 0x0020 /* software: use writethrough cache */
#define _PAGE_RW 0x0040 /* software: user write access allowed */
#define _PAGE_ACCESSED 0x0080 /* software: page referenced */
-#define _PAGE_DIRTY 0x0100 /* C: page changed (write protect) */
+#define _PAGE_HWWRITE 0x0100 /* C: page changed (write protect) */
#define _PAGE_USER 0x0800 /* One of the PP bits, the other must be 0 */
-/* This is used to enable or disable the actual hardware write
- * protection.
- */
-#define _PAGE_HWWRITE _PAGE_DIRTY
-
#else /* CONFIG_6xx */
/* Definitions for 60x, 740/750, etc. */
#define _PAGE_PRESENT 0x001 /* software: pte contains a translation */
}
extern pgd_t swapper_pg_dir[1024];
+extern void paging_init(void);
/*
* Page tables may have changed. We don't need to do anything here
#ifndef _PPC_POSIX_TYPES_H
#define _PPC_POSIX_TYPES_H
+#include <linux/config.h> /* for CONFIG_PPC64 */
+
/*
* This file is generally used by user-level software, so you need to
* be a little careful about namespace pollution etc. Also, we cannot
typedef int __kernel_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
+
+/* Grrr... gcc thinks size_t is unsigned int, so we either
+ have to have this nonsense or use -fno-builtin. - paulus */
+#ifdef CONFIG_PPC64
typedef unsigned long __kernel_size_t;
typedef long __kernel_ssize_t;
+#else
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+#endif /* CONFIG_PPC64 */
+
typedef long __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
#define PVR_8260 PVR_8240
+/* I am just adding a single entry for 8260 boards. I think we may be
+ * able to combine mbx, fads, rpxlite, bseip, and classic into a single
+ * generic 8xx as well. The boards containing these processors are either
+ * identical at the processor level (due to the high integration) or so
+ * wildly different that testing _machine at run time is best replaced by
+ * conditional compilation by board type (found in their respective .h file).
+ * -- Dan
+ */
#define _MACH_prep 0x00000001
#define _MACH_Pmac 0x00000002 /* pmac or pmac clone (non-chrp) */
#define _MACH_chrp 0x00000004 /* chrp machine */
#define _MACH_classic 0x00000400 /* RPCG RPX-Classic 8xx board */
#define _MACH_oak 0x00000800 /* IBM "Oak" 403 eval. board */
#define _MACH_walnut 0x00001000 /* IBM "Walnut" 405GP eval. board */
+#define _MACH_8260 0x00002000 /* Generic 8260 */
/* see residual.h for these */
#elif defined(CONFIG_GEMINI)
#define _machine _MACH_gemini
#define have_of 0
+#elif defined(CONFIG_8260)
+#define _machine _MACH_8260
+#define have_of 0
#else
#error "Machine not defined correctly"
#endif
#define RLIM_NLIMITS 10
+#ifdef __KERNEL__
+
/*
* SuS says limits have to be unsigned.
* Which makes a ton more sense anyway.
#define RLIM_INFINITY (~0UL)
-#ifdef __KERNEL__
-
#define INIT_RLIMITS \
{ \
{ RLIM_INFINITY, RLIM_INFINITY }, \
/* Machine type
*/
-#define _MACH_8xx (_MACH_rpxclassic)
+#define _MACH_8xx (_MACH_classic)
#endif
#ifdef __KERNEL__
#include <asm/atomic.h>
+#include <asm/system.h>
#include <linux/wait.h>
struct semaphore {
#include <linux/config.h>
#include <linux/kdev_t.h>
+#include <linux/bitops.h>
#include <asm/processor.h>
#include <asm/atomic.h>
#define ICRNL 0000400
#define IXON 0001000
#define IXOFF 0002000
-#if defined(__KERNEL__) || defined(__USE_BSD)
- /* POSIX.1 doesn't want these... */
-# define IXANY 0004000
-# define IUCLC 0010000
-# define IMAXBEL 0020000
-#endif
+#define IXANY 0004000
+#define IUCLC 0010000
+#define IMAXBEL 0020000
/* c_oflag bits */
#define OPOST 0000001
#define D_TX 256 /* show tx packets */
#define D_RX 512 /* show rx packets */
#define D_SKB 1024 /* show skb's */
-#define D_TIMING 2048 /* show time needed to copy buffers to card */
+#define D_SKB_SIZE 2048 /* show skb sizes */
+#define D_TIMING 4096 /* show time needed to copy buffers to card */
#ifndef ARCNET_DEBUG_MAX
#define ARCNET_DEBUG_MAX (~0) /* enable ALL debug messages */
#define NORMALconf 0x00 /* 1-249 byte packets */
#define EXTconf 0x08 /* 250-504 byte packets */
+/* card feature flags, set during auto-detection.
+ * (currently only used by com20020pci)
+ */
+#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */
+#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit,
+ but default is 2.5MBit. */
+
/* information needed to define an encapsulation driver */
struct ArcProto {
uint8_t config, /* current value of CONFIG register */
timeout, /* Extended timeout for COM20020 */
backplane, /* Backplane flag for COM20020 */
- clock, /* COM20020 clock speed flag */
- setup, /* Contents of setup register */
+ clockp, /* COM20020 clock divider */
+ clockm, /* COM20020 clock multiplier flag */
+ setup, /* Contents of setup1 register */
+ setup2, /* Contents of setup2 register */
intmask; /* current value of INTMASK register */
uint8_t default_proto[256]; /* default encap to use for each host */
int cur_tx, /* buffer used by current transmit, or -1 */
cur_rx; /* current receive buffer */
int lastload_dest, /* can last loaded packet be acked? */
lasttrans_dest; /* can last TX'd packet be acked? */
- int basename_len; /* name length without suffix ('arc0e' -> 4) */
+ char *card_name; /* card ident string */
+ int card_flags; /* special card features */
/*
* Buffer management: an ARCnet card has 4 x 512-byte buffers, each of
if (coda_debug & mask) { \
printk("(%s,l. %d): ", __FUNCTION__, __LINE__); \
printk(format, ## a); } \
-} while (0) ;
+} while (0)
#define ENTRY \
if(coda_print_entry) printk("Process %d entered %s\n",current->pid,__FUNCTION__)
int com20020_check(struct net_device *dev);
int com20020_found(struct net_device *dev, int shared);
+void com20020_remove(struct net_device *dev);
/* The number of low I/O ports used by the card. */
#define ARCNET_TOTAL_SIZE 9
#define _ADDR_HI (ioaddr+2) /* control registers for IO-mapped memory */
#define _ADDR_LO (ioaddr+3)
#define _MEMDATA (ioaddr+4) /* data port for IO-mapped memory */
+#define _SUBADR (ioaddr+5) /* the extended port _XREG refers to */
#define _CONFIG (ioaddr+6) /* configuration register */
-#define _SETUP (ioaddr+7) /* setup register */
+#define _XREG (ioaddr+7) /* extra registers (indexed by _CONFIG
+ or _SUBADR) */
/* in the ADDR_HI register */
#define RDDATAflag 0x80 /* next access is a read (not a write) */
/* in SETUP register */
#define PROMISCset 0x10 /* enable RCV_ALL */
-#define REGTENTID (lp->config &= ~3);
-#define REGNID (lp->config = (lp->config&~2)|1);
-#define REGSETUP (lp->config = (lp->config&~1)|2);
-#define REGNXTID (lp->config |= 3);
+/* COM2002x */
+#define SUB_TENTATIVE 0 /* tentative node ID */
+#define SUB_NODE 1 /* node ID */
+#define SUB_SETUP1 2 /* various options */
+#define SUB_TEST 3 /* test/diag register */
+
+/* COM20022 only */
+#define SUB_SETUP2 4 /* sundry options */
+#define SUB_BUSCTL 5 /* bus control options */
+#define SUB_DMACOUNT 6 /* DMA count options */
+
+#define SET_SUBADR(x) do { \
+ if ((x) < 4) \
+ { \
+ lp->config = (lp->config & ~0x03) | (x); \
+ SETCONF; \
+ } \
+ else \
+ { \
+ outb(x, _SUBADR); \
+ } \
+} while (0)
#undef ARCRESET
#undef ASTATUS
#define ACOMMAND(cmd) outb((cmd),_COMMAND)
#define AINTMASK(msk) outb((msk),_INTMASK)
-#define SETCONF(cfg) outb(cfg, _CONFIG)
+#define SETCONF outb(lp->config, _CONFIG)
#endif /* __COM20020_H */
extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
-extern int may_umount(struct super_block *);
+extern int may_umount(struct vfsmount *);
static inline int vfs_statfs(struct super_block *sb, struct statfs *buf)
{
#define PG_slab 8
#define PG_swap_cache 9
#define PG_skip 10
-#define PG_swap_entry 11
+#define PG_unused_03 11
#define PG_highmem 12
/* bits 21-30 unused */
#define PG_reserved 31
#define PageClearSwapCache(page) clear_bit(PG_swap_cache, &(page)->flags)
#define PageTestandClearSwapCache(page) test_and_clear_bit(PG_swap_cache, &(page)->flags)
-#define PageSwapEntry(page) test_bit(PG_swap_entry, &(page)->flags)
-#define SetPageSwapEntry(page) set_bit(PG_swap_entry, &(page)->flags)
-#define ClearPageSwapEntry(page) clear_bit(PG_swap_entry, &(page)->flags)
#ifdef CONFIG_HIGHMEM
#define PageHighMem(page) test_bit(PG_highmem, &(page)->flags)
* (i.e. as seen by users in the "Space.c" file). It is the name
* the interface.
*/
- char *name;
+ char name[IFNAMSIZ];
/*
* I/O specific fields
ntfs_u32 at_standard_information;
ntfs_u32 at_attribute_list;
ntfs_u32 at_file_name;
+ ntfs_u32 at_volume_version;
ntfs_u32 at_security_descriptor;
+ ntfs_u32 at_volume_name;
+ ntfs_u32 at_volume_information;
ntfs_u32 at_data;
ntfs_u32 at_index_root;
ntfs_u32 at_index_allocation;
#define PCI_DEVICE_ID_SI_5571 0x5571
#define PCI_DEVICE_ID_SI_5591 0x5591
#define PCI_DEVICE_ID_SI_5597 0x5597
+#define PCI_DEVICE_ID_SI_5598 0x5598
#define PCI_DEVICE_ID_SI_5600 0x5600
#define PCI_DEVICE_ID_SI_6306 0x6306
#define PCI_DEVICE_ID_SI_6326 0x6326
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
- unsigned long min_flt, maj_flt, rss, total_vm, locked_vm;
+ unsigned long rss, total_vm, locked_vm;
unsigned long def_flags;
unsigned long cpu_vm_mask;
unsigned long swap_cnt; /* number of pages to swap on next pass */
0, 0, 0, 0, \
0, 0, 0, \
0, 0, 0, 0, \
- 0, 0, 0, 0, 0, \
+ 0, 0, 0, \
0, 0, 0, 0, NULL }
struct signal_struct {
struct inode **);
extern int swap_duplicate(swp_entry_t);
extern int swap_count(struct page *);
-extern swp_entry_t acquire_swap_entry(struct page *page);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
#define get_swap_page() __get_swap_page(1)
extern void __swap_free(swp_entry_t, unsigned short);
#define _LINUX_TIMER_H
#include <linux/config.h>
+#include <linux/list.h>
/*
* Old-style timers. Please don't use for any new code.
* to distinguish between the different invocations.
*/
struct timer_list {
- struct timer_list *next; /* MUST be first element */
- struct timer_list *prev;
+ struct list_head list;
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);
};
extern void add_timer(struct timer_list * timer);
-extern int del_timer(struct timer_list * timer);
+extern int del_timer(struct timer_list * timer);
/*
* mod_timer is a more efficient way to update the expire field of an
extern inline void init_timer(struct timer_list * timer)
{
- timer->next = NULL;
- timer->prev = NULL;
+ timer->list.next = timer->list.prev = NULL;
#ifdef CONFIG_SMP
timer->running = 0;
#endif
}
-extern inline int timer_pending(const struct timer_list * timer)
+extern inline int timer_pending (const struct timer_list * timer)
{
- return timer->prev != NULL;
+ return timer->list.next != NULL;
}
#ifdef CONFIG_SMP
struct clip_priv {
- char name[8]; /* interface name */
int number; /* for convenience ... */
spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */
struct net_device_stats stats;
static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_opt *tp)
{
- if (!tp->packets_out && !tp->probe_timer.prev)
+ if (!tp->packets_out && !timer_pending(&tp->probe_timer))
tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
}
switch (what) {
case TCP_TIME_RETRANS:
- ret = tp->retransmit_timer.prev != NULL;
+ ret = timer_pending(&tp->retransmit_timer);
break;
case TCP_TIME_DACK:
- ret = tp->delack_timer.prev != NULL;
+ ret = timer_pending(&tp->delack_timer);
break;
case TCP_TIME_PROBE0:
- ret = tp->probe_timer.prev != NULL;
+ ret = timer_pending(&tp->probe_timer);
break;
default:
ret = 0;
(*rss)++;
pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
SHM_ENTRY(shp, idx) = pte;
- } else
- --current->maj_flt; /* was incremented in do_no_page */
+ }
/* pte_val(pte) == SHM_ENTRY (shp, idx) */
get_page(pte_page(pte));
- current->min_flt++;
return pte_page(pte);
oom:
/*
* 'fork.c' contains the help-routines for the 'fork' system call
- * (see also system_call.s).
+ * (see also entry.S and others).
* Fork is rather simple, once you get the hang of it, but the memory
- * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
+ * management can be a bitch. See 'mm/memory.c': 'copy_page_tables()'
*/
#include <linux/config.h>
sched_data->last_schedule = get_cycles();
}
+extern void init_timervecs (void);
+
void __init sched_init(void)
{
/*
for(nr = 0; nr < PIDHASH_SZ; nr++)
pidhash[nr] = NULL;
+ init_timervecs();
+
init_bh(TIMER_BH, timer_bh);
init_bh(TQUEUE_BH, tqueue_bh);
init_bh(IMMEDIATE_BH, immediate_bh);
#define TVR_MASK (TVR_SIZE - 1)
struct timer_vec {
- int index;
- struct timer_list *vec[TVN_SIZE];
+ int index;
+ struct list_head vec[TVN_SIZE];
};
struct timer_vec_root {
- int index;
- struct timer_list *vec[TVR_SIZE];
+ int index;
+ struct list_head vec[TVR_SIZE];
};
static struct timer_vec tv5 = { 0 };
#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0]))
-static unsigned long timer_jiffies = 0;
-
-static inline void insert_timer(struct timer_list *timer, struct timer_list **vec)
+void init_timervecs (void)
{
- struct timer_list *next = *vec;
+ int i;
- timer->next = next;
- if (next)
- next->prev = timer;
- *vec = timer;
- timer->prev = (struct timer_list *)vec;
+ for (i = 0; i < TVN_SIZE; i++) {
+ INIT_LIST_HEAD(tv5.vec + i);
+ INIT_LIST_HEAD(tv4.vec + i);
+ INIT_LIST_HEAD(tv3.vec + i);
+ INIT_LIST_HEAD(tv2.vec + i);
+ }
+ for (i = 0; i < TVR_SIZE; i++)
+ INIT_LIST_HEAD(tv1.vec + i);
}
+static unsigned long timer_jiffies = 0;
+
static inline void internal_add_timer(struct timer_list *timer)
{
/*
*/
unsigned long expires = timer->expires;
unsigned long idx = expires - timer_jiffies;
- struct timer_list ** vec;
+ struct list_head * vec;
if (idx < TVR_SIZE) {
int i = expires & TVR_MASK;
vec = tv5.vec + i;
} else {
/* Can only get here on architectures with 64-bit jiffies */
- timer->next = timer->prev = timer;
+ INIT_LIST_HEAD(&timer->list);
return;
}
- insert_timer(timer, vec);
+ /*
+ * Timers are FIFO!
+ */
+ list_add(&timer->list, vec->prev);
}
spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
- if (timer->prev)
+ if (timer->list.next)
goto bug;
internal_add_timer(timer);
out:
goto out;
}
-static inline int detach_timer(struct timer_list *timer)
+static inline int detach_timer (struct timer_list *timer)
{
- struct timer_list *prev = timer->prev;
- if (prev) {
- struct timer_list *next = timer->next;
- prev->next = next;
- if (next)
- next->prev = prev;
- return 1;
- }
- return 0;
+ if (!timer_pending(timer))
+ return 0;
+ list_del(&timer->list);
+ return 1;
}
int mod_timer(struct timer_list *timer, unsigned long expires)
spin_lock_irqsave(&timerlist_lock, flags);
ret = detach_timer(timer);
- timer->next = timer->prev = 0;
+ timer->list.next = timer->list.prev = NULL;
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}
spin_lock_irqsave(&timerlist_lock, flags);
ret += detach_timer(timer);
- timer->next = timer->prev = 0;
+ timer->list.next = timer->list.prev = 0;
running = timer->running;
spin_unlock_irqrestore(&timerlist_lock, flags);
static inline void cascade_timers(struct timer_vec *tv)
{
- /* cascade all the timers from tv up one level */
- struct timer_list *timer;
- timer = tv->vec[tv->index];
- /*
- * We are removing _all_ timers from the list, so we don't have to
- * detach them individually, just clear the list afterwards.
- */
- while (timer) {
- struct timer_list *tmp = timer;
- timer = timer->next;
- internal_add_timer(tmp);
- }
- tv->vec[tv->index] = NULL;
- tv->index = (tv->index + 1) & TVN_MASK;
+ /* cascade all the timers from tv up one level */
+ struct list_head *head, *curr, *next;
+
+ head = tv->vec + tv->index;
+ curr = head->next;
+ /*
+ * We are removing _all_ timers from the list, so we don't have to
+ * detach them individually, just clear the list afterwards.
+ */
+ while (curr != head) {
+ struct timer_list *tmp;
+
+ tmp = list_entry(curr, struct timer_list, list);
+ next = curr->next;
+ list_del(curr); // not needed
+ internal_add_timer(tmp);
+ curr = next;
+ }
+ INIT_LIST_HEAD(head);
+ tv->index = (tv->index + 1) & TVN_MASK;
}
static inline void run_timer_list(void)
{
spin_lock_irq(&timerlist_lock);
while ((long)(jiffies - timer_jiffies) >= 0) {
- struct timer_list *timer;
+ struct list_head *head, *curr;
if (!tv1.index) {
int n = 1;
do {
cascade_timers(tvecs[n]);
} while (tvecs[n]->index == 1 && ++n < NOOF_TVECS);
}
- while ((timer = tv1.vec[tv1.index])) {
- void (*fn)(unsigned long) = timer->function;
- unsigned long data = timer->data;
+repeat:
+ head = tv1.vec + tv1.index;
+ curr = head->next;
+ if (curr != head) {
+ struct timer_list *timer;
+ void (*fn)(unsigned long);
+ unsigned long data;
+
+ timer = list_entry(curr, struct timer_list, list);
+ fn = timer->function;
+ data= timer->data;
+
detach_timer(timer);
- timer->next = timer->prev = NULL;
+ timer->list.next = timer->list.prev = NULL;
timer_set_running(timer);
spin_unlock_irq(&timerlist_lock);
fn(data);
spin_lock_irq(&timerlist_lock);
+ goto repeat;
}
++timer_jiffies;
tv1.index = (tv1.index + 1) & TVR_MASK;
/* Bump the maxerror field */
time_maxerror += time_tolerance >> SHIFT_USEC;
if ( time_maxerror > NTP_PHASE_LIMIT ) {
- time_maxerror = NTP_PHASE_LIMIT;
+ time_maxerror = NTP_PHASE_LIMIT;
time_status |= STA_UNSYNC;
}
map_nr = pte_pagenr(pte);
if (map_nr >= max_mapnr)
goto bad_wp_page;
- mm->min_flt++;
old_page = mem_map + map_nr;
/*
flush_cache_page(vma, address);
establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
spin_unlock(&mm->page_table_lock);
- return 1;
+ return 1; /* Minor fault */
}
/*
}
spin_unlock(&mm->page_table_lock);
__free_page(new_page);
- return 1;
+ return 1; /* Minor fault */
bad_wp_page:
spin_unlock(&mm->page_table_lock);
}
mm->rss++;
- mm->min_flt++;
pte = mk_pte(page, vma->vm_page_prot);
- SetPageSwapEntry(page);
-
/*
* Freeze the "shared"ness of the page, ie page_count + swap_count.
* Must lock page before transferring our swap count to already
set_pte(page_table, pte);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, address, pte);
- return 1;
+ return 1; /* Minor fault */
}
/*
clear_user_highpage(page, addr);
entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
mm->rss++;
- mm->min_flt++;
flush_page_to_ram(page);
}
set_pte(page_table, entry);
/* No need to invalidate - it was non-present before */
update_mmu_cache(vma, addr, entry);
- return 1;
+ return 1; /* Minor fault */
}
/*
return 0;
if (new_page == NOPAGE_OOM)
return -1;
- ++mm->maj_flt;
++mm->rss;
/*
* This silly early PAGE_DIRTY setting removes a race
set_pte(page_table, entry);
/* no need to invalidate: a not-present page shouldn't be cached */
update_mmu_cache(vma, address, entry);
- return 1;
+ return 2; /* Major fault */
}
/*
PAGE_BUG(page);
if (PageSwapCache(page))
PAGE_BUG(page);
+ if (page->mapping)
+ PAGE_BUG(page);
+ /* needs sync_page to wait I/O completation */
+ page->mapping = &swapper_space;
if (!rw_swap_page_base(rw, entry, page, wait))
UnlockPage(page);
+ page->mapping = NULL;
}
}
UnlockPage(page);
}
-
- ClearPageSwapEntry(page);
-
__free_page(page);
}
goto out;
}
-/* needs the big kernel lock */
-swp_entry_t acquire_swap_entry(struct page *page)
-{
- struct swap_info_struct * p;
- unsigned long offset, type;
- swp_entry_t entry;
-
- if (!PageSwapEntry(page))
- goto new_swap_entry;
-
- /* We have the old entry in the page offset still */
- if (!page->index)
- goto new_swap_entry;
- entry.val = page->index;
- type = SWP_TYPE(entry);
- if (type >= nr_swapfiles)
- goto new_swap_entry;
- p = type + swap_info;
- if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
- goto new_swap_entry;
- offset = SWP_OFFSET(entry);
- if (offset >= p->max)
- goto new_swap_entry;
- /* Has it been re-used for something else? */
- swap_list_lock();
- swap_device_lock(p);
- if (p->swap_map[offset])
- goto unlock_new_swap_entry;
-
- /* We're cool, we can just use the old one */
- p->swap_map[offset] = 1;
- swap_device_unlock(p);
- nr_swap_pages--;
- swap_list_unlock();
- return entry;
-
-unlock_new_swap_entry:
- swap_device_unlock(p);
- swap_list_unlock();
-new_swap_entry:
- return get_swap_page();
-}
-
/*
* The swap entry has been read in advance, and we return 1 to indicate
* that the page has been used or is no longer needed.
* we have the swap cache set up to associate the
* page with that swap entry.
*/
- entry = acquire_swap_entry(page);
+ entry = get_swap_page();
if (!entry.val)
goto out_failed; /* No swap space left */
if (!p->swappable || !mm || mm->rss <= 0)
continue;
/* small processes are swapped out less */
- while ((mm->swap_cnt << 2 * (i + 1) < max_cnt)
- && i++ < 10)
+ while ((mm->swap_cnt << 2 * (i + 1) < max_cnt) && i++ < 10)
+ /* nothing */;
mm->swap_cnt >>= i;
mm->swap_cnt += i; /* if swap_cnt reaches 0 */
/* we're big -> hog treatment */
if (!dev) return -ENOMEM;
memset(dev,0,sizeof(struct net_device)+sizeof(struct clip_priv));
clip_priv = PRIV(dev);
- dev->name = clip_priv->name;
sprintf(dev->name,"atm%d",number);
dev->init = clip_init;
spin_lock_init(&clip_priv->xoff_lock);
struct net_device *dev_alloc(const char *name, int *err)
{
- struct net_device *dev=kmalloc(sizeof(struct net_device)+16, GFP_KERNEL);
+ struct net_device *dev=kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (dev == NULL) {
*err = -ENOBUFS;
return NULL;
}
memset(dev, 0, sizeof(struct net_device));
- dev->name = (char *)(dev + 1); /* Name string space */
*err = dev_alloc_name(dev, name);
if (*err < 0) {
kfree(dev);
static void dst_run_gc(unsigned long);
static struct timer_list dst_gc_timer =
- { NULL, NULL, DST_GC_MIN, 0L, dst_run_gc };
+ { data: DST_GC_MIN, function: dst_run_gc };
static void dst_run_gc(unsigned long dummy)
static void peer_check_expire(unsigned long dummy);
static struct timer_list peer_periodic_timer =
- { NULL, NULL, 0, 0, &peer_check_expire };
+ { { NULL, NULL }, 0, 0, &peer_check_expire };
int inet_peer_gc_mintime = 10 * HZ,
inet_peer_gc_maxtime = 120 * HZ;
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
set_sockaddr(sin, ic_myaddr, 0);
if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n",
- NIPQUAD(err));
+ printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
return -1;
}
set_sockaddr(sin, ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n",
- NIPQUAD(err));
+ printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
return -1;
}
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n",
- NIPQUAD(err));
+ printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
return -1;
}
return 0;
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
rm.rt_flags = RTF_UP | RTF_GATEWAY;
if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
- printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n",
- NIPQUAD(err));
+ printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err);
return -1;
}
}
src = sp->rcv_saddr;
destp = 0;
srcp = sp->num;
- timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_active = (timer_pending(&sp->timer)) ? 2 : 0;
timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
srcp = ntohs(sp->sport);
timer_active = 0;
timer_expires = (unsigned) -1;
- if (tp->retransmit_timer.prev != NULL && tp->retransmit_timer.expires < timer_expires) {
+ if (timer_pending(&tp->retransmit_timer) && tp->retransmit_timer.expires < timer_expires) {
timer_active = 1;
timer_expires = tp->retransmit_timer.expires;
- } else if (tp->probe_timer.prev != NULL && tp->probe_timer.expires < timer_expires) {
+ } else if (timer_pending(&tp->probe_timer) && tp->probe_timer.expires < timer_expires) {
timer_active = 4;
timer_expires = tp->probe_timer.expires;
}
- if (sp->timer.prev != NULL && sp->timer.expires < timer_expires) {
+ if (timer_pending(&sp->timer) && sp->timer.expires < timer_expires) {
timer_active = 2;
timer_expires = sp->timer.expires;
}
static int tcp_twcal_hand = -1;
static int tcp_twcal_jiffie;
static void tcp_twcal_tick(unsigned long);
-static struct timer_list tcp_twcal_timer = {NULL, NULL, 0, 0, tcp_twcal_tick,};
+static struct timer_list tcp_twcal_timer = {function: tcp_twcal_tick};
static struct tcp_tw_bucket *tcp_twcal_row[TCP_TW_RECYCLE_SLOTS];
void tcp_tw_schedule(struct tcp_tw_bucket *tw, int timeo)
src = sp->rcv_saddr;
destp = ntohs(sp->dport);
srcp = ntohs(sp->sport);
- timer_active = (sp->timer.prev != NULL) ? 2 : 0;
+ timer_active = timer_pending(&sp->timer) ? 2 : 0;
timer_expires = (timer_active == 2 ? sp->timer.expires : jiffies);
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
}
#endif
BUG_TRAP(dev->qdisc_list == NULL);
- BUG_TRAP(dev->watchdog_timer.prev == NULL);
+ BUG_TRAP(!timer_pending(&dev->watchdog_timer));
dev->qdisc_list = NULL;
spin_unlock_bh(&dev->queue_lock);
write_unlock(&qdisc_tree_lock);
}
file->f_dentry = d_alloc_root(sock->inode);
+ /* MOUNT_REWRITE: set to sockfs internal vfsmnt */
+ file->f_vfsmnt = NULL;
if (!file->f_dentry) {
put_filp(file);
put_unused_fd(fd);