Commit 3e391afe authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.28pre1

parent 9334eab8
...@@ -543,7 +543,7 @@ CONFIG_ALPHA_AVANTI ...@@ -543,7 +543,7 @@ CONFIG_ALPHA_AVANTI
choices: choices:
** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400) ** Avanti: This is for Mustang (AS200), M3 (AS250), Avanti (AS400)
and XL (a.k.a. "Windows NT Dream Machine" :-) AlphaStations. and XL (a.k.a. "Windows NT Dream Machine" :-) AlphaStations.
These usually come with a TGA graphics adaptor, so you'll want to These usually come with a TGA graphics adapter, so you'll want to
say Y to "TGA Console support", below, if you have one of these. say Y to "TGA Console support", below, if you have one of these.
** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha ** Jensen: a.k.a. DEC 2000 a.k.a. DECpc AXP 150, the oldest Alpha
PC; it sports an EISA bus. The boot process on Jensen machines is PC; it sports an EISA bus. The boot process on Jensen machines is
...@@ -595,11 +595,52 @@ CONFIG_SERIAL_ECHO ...@@ -595,11 +595,52 @@ CONFIG_SERIAL_ECHO
corresponds to a serial port; this could be useful if you attached corresponds to a serial port; this could be useful if you attached
a terminal or printer to that port. a terminal or printer to that port.
Non-standard serial port support
CONFIG_SERIAL_NONSTANDARD
Say Y here if you have any non-standard serial boards --- boards
which aren't supported using the standard "dumb" serial driver.
This includes intelligent serial boards such as Cyclades,
Digiboards, etc.
Extended dumb serial driver options
CONFIG_SERIAL_EXTENDED
If you wish to use any non-standard features of the standard "dumb"
driver, say Y here. This includes HUB6 support, shared serial
interrupts, special multiport support, support for more than the
four COM 1/2/3/4 boards, etc.
Support more than 4 serial ports
CONFIG_SERIAL_MANY_PORTS
Enable this option if you have dumb serial boards other than the
four standard COM 1/2/3/4 ports. This may happen if you have an AST
FourPort, Accent Async, Boca, or other custom serial port hardware
which acts similar to standard serial port hardware. If you only
use the standard COM 1/2/3/4 ports, you can say N here to save some
memory.
Support for sharing serial interrupts
CONFIG_SERIAL_SHARE_IRQ
Some serial boards have hardware support which allows multiple dumb
serial ports on the same board to share a single IRQ. To enable
support for this in the serial driver, say Y here.
Support special multiport boards
CONFIG_SERIAL_MULTIPORT
Some multiport serial ports have special ports which are used to
signal when there are any serial ports on the board which need
servicing. Say Y here to enable the serial driver to take advantage
of those special I/O ports.
Support the Bell Technologies HUB6 card
CONFIG_HUB6
Say Y here to enable support in the dumb serial driver to support
the HUB6 card.
TGA Console Support TGA Console Support
CONFIG_TGA_CONSOLE CONFIG_TGA_CONSOLE
Many Alpha systems (e.g the Multia) are shipped with a graphics card Many Alpha systems (e.g the Multia) are shipped with a graphics card
that implements the TGA interface (much like the VGA standard, but that implements the TGA interface (much like the VGA standard, but
older TGA adaptors are *not* VGA compatible). On such systems, you older TGA adapters are *not* VGA compatible). On such systems, you
should say Y here so that the TGA driver rather than the standard should say Y here so that the TGA driver rather than the standard
VGA driver is used. Note that, at this time, there is no X server VGA driver is used. Note that, at this time, there is no X server
for these systems. If unsure, try N. for these systems. If unsure, try N.
...@@ -1393,7 +1434,7 @@ SCSI support? ...@@ -1393,7 +1434,7 @@ SCSI support?
CONFIG_SCSI CONFIG_SCSI
If you want to use a SCSI harddisk, SCSI tapedrive, SCSI CDROM or If you want to use a SCSI harddisk, SCSI tapedrive, SCSI CDROM or
any other SCSI device under Linux, say Y and make sure that you know any other SCSI device under Linux, say Y and make sure that you know
the name of your SCSI host adaptor (the card inside your computer the name of your SCSI host adapter (the card inside your computer
that "speaks" the SCSI protocol), because you will be asked for that "speaks" the SCSI protocol), because you will be asked for
it. You also need to say Y here if you want support for the parallel it. You also need to say Y here if you want support for the parallel
port version of the 100MB IOMEGA ZIP drive. Please read the port version of the 100MB IOMEGA ZIP drive. Please read the
...@@ -1480,7 +1521,7 @@ CONFIG_SCSI_CONSTANTS ...@@ -1480,7 +1521,7 @@ CONFIG_SCSI_CONSTANTS
AdvanSys SCSI support AdvanSys SCSI support
CONFIG_SCSI_ADVANSYS CONFIG_SCSI_ADVANSYS
This is a driver for all SCSI host adaptors manufactured by This is a driver for all SCSI host adapters manufactured by
AdvanSys. It is documented in the kernel source in AdvanSys. It is documented in the kernel source in
drivers/scsi/advansys.c. This driver is also available as a module ( drivers/scsi/advansys.c. This driver is also available as a module (
= code which can be inserted in and removed from the running kernel = code which can be inserted in and removed from the running kernel
...@@ -1491,7 +1532,7 @@ CONFIG_SCSI_ADVANSYS ...@@ -1491,7 +1532,7 @@ CONFIG_SCSI_ADVANSYS
Adaptec AHA152X/2825 support Adaptec AHA152X/2825 support
CONFIG_SCSI_AHA152X CONFIG_SCSI_AHA152X
This is support for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825 This is support for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
SCSI host adaptors. It is explained in section 3.3 of the SCSI host adapters. It is explained in section 3.3 of the
SCSI-HOWTO, available via ftp (user: anonymous) at SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. You might also want to read sunsite.unc.edu:/pub/Linux/docs/HOWTO. You might also want to read
the comments at the top of drivers/scsi/aha152x.c. This driver is the comments at the top of drivers/scsi/aha152x.c. This driver is
...@@ -1502,7 +1543,7 @@ CONFIG_SCSI_AHA152X ...@@ -1502,7 +1543,7 @@ CONFIG_SCSI_AHA152X
Adaptec AHA1542 support Adaptec AHA1542 support
CONFIG_SCSI_AHA1542 CONFIG_SCSI_AHA1542
This is support for a SCSI host adaptor. It is explained in section This is support for a SCSI host adapter. It is explained in section
3.4 of the SCSI-HOWTO, available via ftp (user: anonymous) at 3.4 of the SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that Trantor was sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that Trantor was
recently purchased by Adaptec, and some former Trantor products are recently purchased by Adaptec, and some former Trantor products are
...@@ -1515,7 +1556,7 @@ CONFIG_SCSI_AHA1542 ...@@ -1515,7 +1556,7 @@ CONFIG_SCSI_AHA1542
Adaptec AHA1740 support Adaptec AHA1740 support
CONFIG_SCSI_AHA1740 CONFIG_SCSI_AHA1740
This is support for a SCSI host adaptor. It is explained in section This is support for a SCSI host adapter. It is explained in section
3.5 of the SCSI-HOWTO, available via ftp (user: anonymous) at 3.5 of the SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of
the box, you may have to change some settings in the box, you may have to change some settings in
...@@ -1527,7 +1568,7 @@ CONFIG_SCSI_AHA1740 ...@@ -1527,7 +1568,7 @@ CONFIG_SCSI_AHA1740
Adaptec AHA274X/284X/294X support Adaptec AHA274X/284X/294X support
CONFIG_SCSI_AIC7XXX CONFIG_SCSI_AIC7XXX
Information about this SCSI host adaptor is contained in Information about this SCSI host adapter is contained in
drivers/scsi/README.aic7xxx and in the SCSI-HOWTO, available via ftp drivers/scsi/README.aic7xxx and in the SCSI-HOWTO, available via ftp
(user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it
doesn't work out of the box, you may have to change some settings in doesn't work out of the box, you may have to change some settings in
...@@ -1538,24 +1579,25 @@ CONFIG_SCSI_AIC7XXX ...@@ -1538,24 +1579,25 @@ CONFIG_SCSI_AIC7XXX
BusLogic SCSI support BusLogic SCSI support
CONFIG_SCSI_BUSLOGIC CONFIG_SCSI_BUSLOGIC
This is support for BusLogic MultiMaster SCSI Host Adaptors. This is support for BusLogic MultiMaster and FlashPoint SCSI Host Adapters.
Consult the SCSI-HOWTO, available via anonymous ftp from Consult the SCSI-HOWTO, available via anonymous ftp from sunsite.unc.edu in
sunsite.unc.edu:/pub/Linux/docs/HOWTO and the file /pub/Linux/docs/HOWTO, and the files README.BusLogic and README.FlashPoint in
drivers/scsi/README.BusLogic for more information. BusLogic drivers/scsi for more information. If this driver does not work correctly
FlashPoint SCSI Host Adapters are not supported by this driver, but without modification, please contact the author, Leonard N. Zubkoff, by email
BusLogic has initiated an upgrade program which allows you to get a to lnz@dandelion.com. You can also build this driver as a module ( = code
better adaptor for few $$. Read about it in which can be inserted in and removed from the running kernel whenever you
drivers/scsi/README.FlashPoint. If this driver does not work want), but only a single instance may be loaded. If you want to compile it
correctly without modification, please contact the author. You can as a module, say M here and read Documentation/modules.txt.
build this driver also as a module ( = code which can be inserted in
and removed from the running kernel whenever you want), but only a Omit BusLogic SCSI FlashPoint support
single instance may be loaded. The module will be called CONFIG_SCSI_OMIT_FLASHPOINT
BusLogic.o. If you want to compile it as a module, say M here and This option allows you to omit the FlashPoint support from the BusLogic
read Documentation/modules.txt. SCSI driver. The FlashPoint SCCB Manager code is substantial, so users of
MultiMaster Host Adapters may wish to omit it.
DTC3180/3280 SCSI support DTC3180/3280 SCSI support
CONFIG_SCSI_DTC3280 CONFIG_SCSI_DTC3280
This is support for DTC 3180/3280 SCSI Host Adaptors. Please read This is support for DTC 3180/3280 SCSI Host Adapters. Please read
the SCSI-HOWTO, available via ftp (user: anonymous) at the SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO and the file sunsite.unc.edu:/pub/Linux/docs/HOWTO and the file
drivers/scsi/README.dtc3x80. This driver is also available as a drivers/scsi/README.dtc3x80. This driver is also available as a
...@@ -1567,7 +1609,7 @@ CONFIG_SCSI_DTC3280 ...@@ -1567,7 +1609,7 @@ CONFIG_SCSI_DTC3280
EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support
CONFIG_SCSI_EATA_DMA CONFIG_SCSI_EATA_DMA
This is support for the EATA-DMA protocol compliant SCSI Host This is support for the EATA-DMA protocol compliant SCSI Host
Adaptors like the SmartCache III/IV, SmartRAID controller families Adapters like the SmartCache III/IV, SmartRAID controller families
and the DPT PM2011B and PM2012B controllers. Note that there is and the DPT PM2011B and PM2012B controllers. Note that there is
also another driver for the same hardware: "EATA ISA/EISA/PCI also another driver for the same hardware: "EATA ISA/EISA/PCI
support". You should only say Y to one of them. Please read the support". You should only say Y to one of them. Please read the
...@@ -1581,8 +1623,8 @@ CONFIG_SCSI_EATA_DMA ...@@ -1581,8 +1623,8 @@ CONFIG_SCSI_EATA_DMA
EATA-PIO (old DPT PM2001, PM2012A) support EATA-PIO (old DPT PM2001, PM2012A) support
CONFIG_SCSI_EATA_PIO CONFIG_SCSI_EATA_PIO
This driver supports all EATA-PIO protocol compliant SCSI Host This driver supports all EATA-PIO protocol compliant SCSI Host
Adaptors like the DPT PM2001 and the PM2012A. EATA-DMA compliant Adapters like the DPT PM2001 and the PM2012A. EATA-DMA compliant
host adaptors could also use this driver but are discouraged from host adapters could also use this driver but are discouraged from
doing so, since this driver only supports harddisks and lacks doing so, since this driver only supports harddisks and lacks
numerous features. You might want to have a look at the SCSI-HOWTO, numerous features. You might want to have a look at the SCSI-HOWTO,
available via ftp (user: anonymous) at available via ftp (user: anonymous) at
...@@ -1609,7 +1651,7 @@ CONFIG_SCSI_U14_34F ...@@ -1609,7 +1651,7 @@ CONFIG_SCSI_U14_34F
enable linked commands enable linked commands
CONFIG_SCSI_U14_34F_LINKED_COMMANDS CONFIG_SCSI_U14_34F_LINKED_COMMANDS
This is a feature of SCSI-2 which improves performance: the host This is a feature of SCSI-2 which improves performance: the host
adaptor can send a whole list of commands to a device in one adapter can send a whole list of commands to a device in one
batch. Some SCSI devices might not implement this properly, so the batch. Some SCSI devices might not implement this properly, so the
save answer is N. save answer is N.
...@@ -1621,9 +1663,9 @@ CONFIG_SCSI_U14_34F_MAX_TAGS ...@@ -1621,9 +1663,9 @@ CONFIG_SCSI_U14_34F_MAX_TAGS
Future Domain 16xx SCSI support Future Domain 16xx SCSI support
CONFIG_SCSI_FUTURE_DOMAIN CONFIG_SCSI_FUTURE_DOMAIN
This is support for Future Domain's 16-bit SCSI host adaptors This is support for Future Domain's 16-bit SCSI host adapters
(TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and (TMC-1660/1680, TMC-1650/1670, TMC-3260, TMC-1610M/MER/MEX) and
other adaptors based on the Future Domain chipsets (Quantum other adapters based on the Future Domain chipsets (Quantum
ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board). ISA-200S, ISA-250MG; Adaptec AHA-2920; and at least one IBM board).
It is explained in section 3.7 of the SCSI-HOWTO, available via ftp It is explained in section 3.7 of the SCSI-HOWTO, available via ftp
(user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. This (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. This
...@@ -1682,7 +1724,7 @@ CONFIG_SCSI_NCR53C7xx_sync ...@@ -1682,7 +1724,7 @@ CONFIG_SCSI_NCR53C7xx_sync
allow FAST-SCSI [10MHz] allow FAST-SCSI [10MHz]
CONFIG_SCSI_NCR53C7xx_FAST CONFIG_SCSI_NCR53C7xx_FAST
This will enable 10MHz FAST-SCSI transfers with your host This will enable 10MHz FAST-SCSI transfers with your host
adaptor. Some systems have problems with that speed, so it's safest adapter. Some systems have problems with that speed, so it's safest
to say N here. to say N here.
allow DISCONNECT allow DISCONNECT
...@@ -1779,7 +1821,7 @@ CONFIG_SCSI_IBMMCA ...@@ -1779,7 +1821,7 @@ CONFIG_SCSI_IBMMCA
Always IN2000 SCSI support Always IN2000 SCSI support
CONFIG_SCSI_IN2000 CONFIG_SCSI_IN2000
This is support for an ISA bus SCSI host adaptor. You'll find more This is support for an ISA bus SCSI host adapter. You'll find more
information in drivers/scsi/in2000.readme. If it doesn't work out of information in drivers/scsi/in2000.readme. If it doesn't work out of
the box, you may have to change the jumpers for IRQ or address the box, you may have to change the jumpers for IRQ or address
selection. If you want to compile this as a module ( = code which selection. If you want to compile this as a module ( = code which
...@@ -1789,7 +1831,7 @@ CONFIG_SCSI_IN2000 ...@@ -1789,7 +1831,7 @@ CONFIG_SCSI_IN2000
PAS16 SCSI support PAS16 SCSI support
CONFIG_SCSI_PAS16 CONFIG_SCSI_PAS16
This is support for a SCSI host adaptor. It is explained in section This is support for a SCSI host adapter. It is explained in section
3.10 of the SCSI-HOWTO, available via ftp (user: anonymous) at 3.10 of the SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the
box, you may have to change some settings in drivers/scsi/pas16.h. box, you may have to change some settings in drivers/scsi/pas16.h.
...@@ -1816,7 +1858,7 @@ CONFIG_SCSI_QLOGIC_FAS ...@@ -1816,7 +1858,7 @@ CONFIG_SCSI_QLOGIC_FAS
Qlogic ISP SCSI support (EXPERIMENTAL) Qlogic ISP SCSI support (EXPERIMENTAL)
CONFIG_SCSI_QLOGIC_ISP CONFIG_SCSI_QLOGIC_ISP
This driver works for all QLogic PCI SCSI host adaptors (IQ-PCI, This driver works for all QLogic PCI SCSI host adapters (IQ-PCI,
IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
card is supported by the "AM53/79C974 PCI SCSI" driver). If you say card is supported by the "AM53/79C974 PCI SCSI" driver). If you say
Y here, make sure to say Y to "PCI BIOS support" as well. More Y here, make sure to say Y to "PCI BIOS support" as well. More
...@@ -1843,7 +1885,7 @@ CONFIG_SCSI_SEAGATE ...@@ -1843,7 +1885,7 @@ CONFIG_SCSI_SEAGATE
Trantor T128/T128F/T228 SCSI support Trantor T128/T128F/T228 SCSI support
CONFIG_SCSI_T128 CONFIG_SCSI_T128
This is support for a SCSI host adaptor. It is explained in section This is support for a SCSI host adapter. It is explained in section
3.11 of the SCSI-HOWTO, available via ftp (user: anonymous) at 3.11 of the SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of
the box, you may have to change some settings in the box, you may have to change some settings in
...@@ -1857,7 +1899,7 @@ CONFIG_SCSI_T128 ...@@ -1857,7 +1899,7 @@ CONFIG_SCSI_T128
UltraStor SCSI support UltraStor SCSI support
CONFIG_SCSI_ULTRASTOR CONFIG_SCSI_ULTRASTOR
This is support for the UltraStor 14F, 24F and 34F SCSI-2 host This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
adaptor family. This driver is explained in section 3.12 of the adapter family. This driver is explained in section 3.12 of the
SCSI-HOWTO, available via ftp (user: anonymous) at SCSI-HOWTO, available via ftp (user: anonymous) at
sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the
box, you may have to change some settings in box, you may have to change some settings in
...@@ -1870,7 +1912,7 @@ CONFIG_SCSI_ULTRASTOR ...@@ -1870,7 +1912,7 @@ CONFIG_SCSI_ULTRASTOR
7000FASST SCSI support 7000FASST SCSI support
CONFIG_SCSI_7000FASST CONFIG_SCSI_7000FASST
This driver supports the Western Digital 7000 SCSI host adaptor. This driver supports the Western Digital 7000 SCSI host adapter.
Some information is in the source: drivers/scsi/wd7000.c. This Some information is in the source: drivers/scsi/wd7000.c. This
driver is also available as a module ( = code which can be inserted driver is also available as a module ( = code which can be inserted
in and removed from the running kernel whenever you want). The in and removed from the running kernel whenever you want). The
...@@ -1896,14 +1938,14 @@ CONFIG_SCSI_EATA ...@@ -1896,14 +1938,14 @@ CONFIG_SCSI_EATA
enable tagged command queuing enable tagged command queuing
CONFIG_SCSI_EATA_TAGGED_QUEUE CONFIG_SCSI_EATA_TAGGED_QUEUE
This is a feature of SCSI-2 which improves performance: the host This is a feature of SCSI-2 which improves performance: the host
adaptor can send several SCSI commands to a device's queue even if adapter can send several SCSI commands to a device's queue even if
previous commands haven't finished yet. Some SCSI devices don't previous commands haven't finished yet. Some SCSI devices don't
implement this properly, so the save answer is N. implement this properly, so the save answer is N.
enable linked commands enable linked commands
CONFIG_SCSI_EATA_LINKED_COMMANDS CONFIG_SCSI_EATA_LINKED_COMMANDS
This is a feature of SCSI-2 which improves performance: the host This is a feature of SCSI-2 which improves performance: the host
adaptor can send a whole list of commands to a device in one adapter can send a whole list of commands to a device in one
batch. Some SCSI devices might not implement this properly, so the batch. Some SCSI devices might not implement this properly, so the
save answer is N. save answer is N.
...@@ -3081,10 +3123,10 @@ CONFIG_ZNET ...@@ -3081,10 +3123,10 @@ CONFIG_ZNET
by this driver. Read the Ethernet-HOWTO, available via ftp (user: by this driver. Read the Ethernet-HOWTO, available via ftp (user:
anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO.
Pocket and portable adaptors Pocket and portable adapters
CONFIG_NET_POCKET CONFIG_NET_POCKET
Cute little network (ethernet) devices which attach to the parallel Cute little network (ethernet) devices which attach to the parallel
port ("pocket adaptors"), commonly used with laptops. If you have port ("pocket adapters"), commonly used with laptops. If you have
one of those, say Y and read the Ethernet-HOWTO, available via ftp one of those, say Y and read the Ethernet-HOWTO, available via ftp
(user: anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you (user: anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you
want to plug a network card into the PCMCIA slot of your laptop want to plug a network card into the PCMCIA slot of your laptop
...@@ -3098,10 +3140,10 @@ CONFIG_NET_POCKET ...@@ -3098,10 +3140,10 @@ CONFIG_NET_POCKET
plan to use more than one network device under linux, read the plan to use more than one network device under linux, read the
Multiple-Ethernet-mini-HOWTO, available from Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use an sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you intend to use an
adaptor attaching to the parallel port as well as a parallel adapter attaching to the parallel port as well as a parallel
printer, you should compile both drivers as modules (if possible). printer, you should compile both drivers as modules (if possible).
AT-LAN-TEC/RealTek pocket adaptor support AT-LAN-TEC/RealTek pocket adapter support
CONFIG_ATP CONFIG_ATP
This is a network (ethernet) device which attaches to your parallel This is a network (ethernet) device which attaches to your parallel
port. Read drivers/net/atp.c as well as the Ethernet-HOWTO, port. Read drivers/net/atp.c as well as the Ethernet-HOWTO,
...@@ -3113,7 +3155,7 @@ CONFIG_ATP ...@@ -3113,7 +3155,7 @@ CONFIG_ATP
this driver, you should have said N to the Parallel Printer support, this driver, you should have said N to the Parallel Printer support,
because the two drivers don't like each other. because the two drivers don't like each other.
D-Link DE600 pocket adaptor support D-Link DE600 pocket adapter support
CONFIG_DE600 CONFIG_DE600
This is a network (ethernet) device which attaches to your parallel This is a network (ethernet) device which attaches to your parallel
port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO,
...@@ -3122,13 +3164,13 @@ CONFIG_DE600 ...@@ -3122,13 +3164,13 @@ CONFIG_DE600
you want to compile this as a module ( = code which can be inserted you want to compile this as a module ( = code which can be inserted
in and removed from the running kernel whenever you want), say M in and removed from the running kernel whenever you want), say M
here and read Documentation/modules.txt. The module will be called here and read Documentation/modules.txt. The module will be called
de600.o. If you intend to use this pocket adaptor as well as a de600.o. If you intend to use this pocket adapter as well as a
parallel printer, you should compile both drivers as modules. If you parallel printer, you should compile both drivers as modules. If you
plan to use more than one network card under linux, read the plan to use more than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from Multiple-Ethernet-mini-HOWTO, available from
sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
D-Link DE620 pocket adaptor support D-Link DE620 pocket adapter support
CONFIG_DE620 CONFIG_DE620
This is a network (ethernet) device which attaches to your parallel This is a network (ethernet) device which attaches to your parallel
port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO, port. Read drivers/net/README.DLINK as well as the Ethernet-HOWTO,
...@@ -3137,7 +3179,7 @@ CONFIG_DE620 ...@@ -3137,7 +3179,7 @@ CONFIG_DE620
you want to compile this as a module ( = code which can be inserted you want to compile this as a module ( = code which can be inserted
in and removed from the running kernel whenever you want), say M in and removed from the running kernel whenever you want), say M
here and read Documentation/modules.txt. The module will be called here and read Documentation/modules.txt. The module will be called
de620.o. If you intend to use this pocket adaptor as well as a de620.o. If you intend to use this pocket adapter as well as a
parallel printer, you should compile both drivers as modules. If you parallel printer, you should compile both drivers as modules. If you
plan to use more than one network card under linux, read the plan to use more than one network card under linux, read the
Multiple-Ethernet-mini-HOWTO, available from Multiple-Ethernet-mini-HOWTO, available from
...@@ -3150,7 +3192,7 @@ CONFIG_TR ...@@ -3150,7 +3192,7 @@ CONFIG_TR
ring network and want to use your Token Ring card under Linux, say Y. ring network and want to use your Token Ring card under Linux, say Y.
Most people can say N here. Most people can say N here.
IBM Tropic chipset based adaptor support IBM Tropic chipset based adapter support
CONFIG_IBMTR CONFIG_IBMTR
This is support for all IBM Token Ring cards that don't use DMA. If This is support for all IBM Token Ring cards that don't use DMA. If
you have such a beast, say Y, otherwise N. Warning: this driver will you have such a beast, say Y, otherwise N. Warning: this driver will
......
...@@ -142,6 +142,7 @@ BUSLOGIC SCSI DRIVER ...@@ -142,6 +142,7 @@ BUSLOGIC SCSI DRIVER
P: Leonard N. Zubkoff P: Leonard N. Zubkoff
M: Leonard N. Zubkoff <lnz@dandelion.com> M: Leonard N. Zubkoff <lnz@dandelion.com>
L: linux-scsi@vger.rutgers.edu L: linux-scsi@vger.rutgers.edu
W: http://www.dandelion.com/Linux/
S: Maintained S: Maintained
CYCLADES ASYNC MUX DRIVER CYCLADES ASYNC MUX DRIVER
...@@ -303,6 +304,12 @@ M: ecd@skynet.be ...@@ -303,6 +304,12 @@ M: ecd@skynet.be
L: sparclinux@vger.rutgers.edu L: sparclinux@vger.rutgers.edu
S: Maintained S: Maintained
SCSI SUBSYSTEM
P: Leonard N. Zubkoff
M: Leonard N. Zubkoff <lnz@dandelion.com>
L: linux-scsi@vger.rutgers.edu
S: Maintained
SVGA HANDLING: SVGA HANDLING:
P: Martin Mares P: Martin Mares
M: mj@k332.feld.cvut.cz M: mj@k332.feld.cvut.cz
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 27 SUBLEVEL = 28
ARCH = i386 ARCH = i386
......
...@@ -125,7 +125,7 @@ entInt: ...@@ -125,7 +125,7 @@ entInt:
lda $0,intr_count lda $0,intr_count
ldl $1,0($0) ldl $1,0($0)
addq $1,1,$1 addq $1,1,$1
stq $1,0($0) stl $1,0($0)
/* set up the arguments to the C interrupt handler */ /* set up the arguments to the C interrupt handler */
ldq $8,current_set ldq $8,current_set
jsr $26,do_entInt jsr $26,do_entInt
...@@ -133,7 +133,7 @@ entInt: ...@@ -133,7 +133,7 @@ entInt:
lda $0,intr_count lda $0,intr_count
ldl $1,0($0) ldl $1,0($0)
subq $1,1,$1 subq $1,1,$1
stq $1,0($0) stl $1,0($0)
br $31,ret_from_sys_call br $31,ret_from_sys_call
.end entInt .end entInt
...@@ -710,7 +710,7 @@ sys_call_table: ...@@ -710,7 +710,7 @@ sys_call_table:
/*0*/ .quad do_entSys, sys_exit, sys_fork, sys_read, sys_write /*0*/ .quad do_entSys, sys_exit, sys_fork, sys_read, sys_write
.quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link .quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link
.quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod .quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod
.quad sys_chmod, sys_chown, sys_brk, do_entSys, sys_lseek .quad sys_chmod, sys_chown, osf_brk, do_entSys, sys_lseek
.quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid .quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid
.quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys .quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys
.quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys .quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys
......
...@@ -47,6 +47,20 @@ extern asmlinkage int sys_umount(char *); ...@@ -47,6 +47,20 @@ extern asmlinkage int sys_umount(char *);
extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
extern asmlinkage unsigned long sys_brk(unsigned long); extern asmlinkage unsigned long sys_brk(unsigned long);
/*
* Brk needs to return an error. Still support Linux's brk(0) query idiom,
* which OSF programs just shouldn't be doing. We're still not quite
* identical to OSF as we don't return 0 on success, but doing otherwise
* would require changes to libc. Hopefully this is good enough.
*/
asmlinkage unsigned long osf_brk(unsigned long brk)
{
unsigned long retval = sys_brk(brk);
if (brk && brk != retval)
retval = -ENOMEM;
return retval;
}
/* /*
* This is pure guess-work.. * This is pure guess-work..
*/ */
......
...@@ -304,20 +304,14 @@ csum_partial_cfu_unaligned(unsigned long * src, unsigned long * dst, ...@@ -304,20 +304,14 @@ csum_partial_cfu_unaligned(unsigned long * src, unsigned long * dst,
return checksum; return checksum;
} }
unsigned int static unsigned int
csum_partial_copy_from_user(int *errp, char *src, char *dst, do_csum_partial_copy_from_user(char *src, char *dst, int len,
int len, unsigned int sum) unsigned int sum, int *errp)
{ {
unsigned long checksum = (unsigned) sum; unsigned long checksum = (unsigned) sum;
unsigned long soff = 7 & (unsigned long) src; unsigned long soff = 7 & (unsigned long) src;
unsigned long doff = 7 & (unsigned long) dst; unsigned long doff = 7 & (unsigned long) dst;
if (!access_ok(src, len, VERIFY_READ)) {
*errp = -EFAULT;
memset(dst, 0, len);
return checksum;
}
if (len) { if (len) {
if (!doff) { if (!doff) {
if (!soff) if (!soff)
...@@ -357,13 +351,26 @@ csum_partial_copy_from_user(int *errp, char *src, char *dst, ...@@ -357,13 +351,26 @@ csum_partial_copy_from_user(int *errp, char *src, char *dst,
return checksum; return checksum;
} }
unsigned int
csum_partial_copy_from_user(char *src, char *dst, int len,
unsigned int sum, int *errp)
{
if (!access_ok(src, len, VERIFY_READ)) {
*errp = -EFAULT;
memset(dst, 0, len);
return sum;
}
return do_csum_partial_copy_from_user(src, dst, len, sum, errp);
}
unsigned int unsigned int
csum_partial_copy (const char *src, char *dst, int len, unsigned int sum) csum_partial_copy (const char *src, char *dst, int len, unsigned int sum)
{ {
unsigned int ret; unsigned int ret;
int error = 0; int error = 0;
ret = csum_partial_copy_from_user(&error, src, dst, len, sum); ret = do_csum_partial_copy_from_user(src, dst, len, sum, &error);
if (error) if (error)
printk("csum_partial_copy_old(): tell mingo to convert me!\n"); printk("csum_partial_copy_old(): tell mingo to convert me!\n");
......
...@@ -120,6 +120,7 @@ CONFIG_SCSI_CONSTANTS=y ...@@ -120,6 +120,7 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_AM53C974 is not set
CONFIG_SCSI_BUSLOGIC=y CONFIG_SCSI_BUSLOGIC=y
CONFIG_SCSI_OMIT_FLASHPOINT=y
# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_DMA is not set
# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_EATA_PIO is not set
...@@ -201,11 +202,8 @@ CONFIG_ISO9660_FS=y ...@@ -201,11 +202,8 @@ CONFIG_ISO9660_FS=y
# Character devices # Character devices
# #
CONFIG_SERIAL=y CONFIG_SERIAL=y
# CONFIG_DIGI is not set # CONFIG_SERIAL_EXTENDED is not set
# CONFIG_CYCLADES is not set # CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_STALDRV is not set
# CONFIG_RISCOM8 is not set
# CONFIG_ESPSERIAL is not set
# CONFIG_PRINTER is not set # CONFIG_PRINTER is not set
CONFIG_MOUSE=y CONFIG_MOUSE=y
# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_ATIXL_BUSMOUSE is not set
......
...@@ -349,7 +349,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) ...@@ -349,7 +349,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
int do_random = 0; int do_random = 0;
lock_kernel(); lock_kernel();
intr_count++; atomic_inc(&intr_count);
#ifdef __SMP__ #ifdef __SMP__
if(smp_threads_ready && active_kernel_processor!=smp_processor_id()) if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id()); panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
...@@ -366,7 +366,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) ...@@ -366,7 +366,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
} }
if (do_random & SA_SAMPLE_RANDOM) if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
intr_count--; atomic_dec(&intr_count);
unlock_kernel(); unlock_kernel();
} }
......
Thu Feb 27 01:53:08 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* serial.c (change_speed): Add support for the termios flag
CMSPAR, which allows the user to select stick parity.
(i.e, if PARODD is set, the the parity bit is always 1; if
PARRODD is not set, then the parity bit is always 0).
Wed Feb 26 19:03:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* serial.c (cleanup_module): Fix memory leak when using the serial
driver as a module; make sure tmp_buf gets freed!
Tue Feb 25 11:01:59 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* serial.c (set_modem_info): Add support for setting and clearing
the OUT1 and OUT2 bits. (For special case UART's, usually
for half-duplex.)
(autoconfig, change_speed): Fix TI 16750 support.
Sun Feb 16 00:14:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* tty_io.c (release_dev): Add sanity check to make sure there are
no waiters on tty->read_wait or tty->write_wait.
* serial.c (rs_init): Don't autoconfig a device if the I/O region
is already reserved.
* serial.c (serial_proc_info): Add support for /proc/serial.
Thu Feb 13 00:49:10 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* serial.c (receive_chars): When the UART repotrs an overrun
condition, it does so with a valid character. Changed to
not throw away the valid character, but instead report the
overrun after the valid character.
* serial.c: Added new #ifdef's for some of the advanced serial
driver features. A minimal driver that only supports COM
1/2/3/4 without sharing serial interrupts only takes 17k;
the full driver takes 32k.
Wed Feb 12 14:50:44 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* vt.c:
* pty.c:
* tty_ioctl.c:
* serial.c: Update routines to use the new 2.1 memory access
routines.
Wed Dec 4 07:51:52 1996 Theodre Ts'o <tytso@localhost.mit.edu> Wed Dec 4 07:51:52 1996 Theodre Ts'o <tytso@localhost.mit.edu>
* serial.c (change_speed): Use save_flags(); cli() and * serial.c (change_speed): Use save_flags(); cli() and
......
...@@ -4,19 +4,29 @@ ...@@ -4,19 +4,29 @@
mainmenu_option next_comment mainmenu_option next_comment
comment 'Character devices' comment 'Character devices'
tristate 'Standard/generic serial support' CONFIG_SERIAL tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
bool 'Digiboard PC/Xx Support' CONFIG_DIGI bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
tristate 'Cyclades async mux support' CONFIG_CYCLADES if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
bool 'Stallion multiport serial support' CONFIG_STALDRV bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
if [ "$CONFIG_STALDRV" = "y" ]; then bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
fi
bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
bool 'Digiboard PC/Xx Support' CONFIG_DIGI
tristate 'Cyclades async mux support' CONFIG_CYCLADES
bool 'Stallion multiport serial support' CONFIG_STALDRV
if [ "$CONFIG_STALDRV" = "y" ]; then
tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION
tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION tristate ' Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
fi fi
tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8 tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
if [ "$CONFIG_ESPSERIAL" = "y" -o "$CONFIG_ESPSERIAL" = "m" ]; then if [ "$CONFIG_ESPSERIAL" = "y" -o "$CONFIG_ESPSERIAL" = "m" ]; then
int ' DMA channel' CONFIG_ESPSERIAL_DMA_CHANNEL 1 int ' DMA channel' CONFIG_ESPSERIAL_DMA_CHANNEL 1
int ' FIFO trigger level' CONFIG_ESPSERIAL_TRIGGER_LEVEL 768 int ' FIFO trigger level' CONFIG_ESPSERIAL_TRIGGER_LEVEL 768
fi
fi fi
tristate 'Parallel printer support' CONFIG_PRINTER tristate 'Parallel printer support' CONFIG_PRINTER
......
...@@ -1010,6 +1010,7 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol ...@@ -1010,6 +1010,7 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol
struct tty_ldisc tty_ldisc_N_TTY = { struct tty_ldisc tty_ldisc_N_TTY = {
TTY_LDISC_MAGIC, /* magic */ TTY_LDISC_MAGIC, /* magic */
"n_tty", /* name */
0, /* num */ 0, /* num */
0, /* flags */ 0, /* flags */
n_tty_open, /* open */ n_tty_open, /* open */
......
...@@ -4,14 +4,6 @@ ...@@ -4,14 +4,6 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
*/ */
/*
* pty.c
*
* This module exports the following pty function:
*
* int pty_open(struct tty_struct * tty, struct file * filp);
*/
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -47,8 +39,8 @@ struct pty_struct { ...@@ -47,8 +39,8 @@ struct pty_struct {
static unsigned char *tmp_buf; static unsigned char *tmp_buf;
static struct semaphore tmp_buf_sem = MUTEX; static struct semaphore tmp_buf_sem = MUTEX;
struct tty_driver pty_driver, pty_slave_driver; static struct tty_driver pty_driver, pty_slave_driver;
struct tty_driver old_pty_driver, old_pty_slave_driver; static struct tty_driver old_pty_driver, old_pty_slave_driver;
static int pty_refcount; static int pty_refcount;
static struct tty_struct *pty_table[NR_PTYS]; static struct tty_struct *pty_table[NR_PTYS];
...@@ -74,8 +66,10 @@ static void pty_close(struct tty_struct * tty, struct file * filp) ...@@ -74,8 +66,10 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
} }
wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->read_wait);
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
tty->packet = 0;
if (!tty->link) if (!tty->link)
return; return;
tty->link->packet = 0;
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait); wake_up_interruptible(&tty->link->write_wait);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
...@@ -125,7 +119,12 @@ static int pty_write(struct tty_struct * tty, int from_user, ...@@ -125,7 +119,12 @@ static int pty_write(struct tty_struct * tty, int from_user,
((tty->driver.subtype-1) * PTY_BUF_SIZE); ((tty->driver.subtype-1) * PTY_BUF_SIZE);
while (count > 0) { while (count > 0) {
n = MIN(count, PTY_BUF_SIZE); n = MIN(count, PTY_BUF_SIZE);
copy_from_user(temp_buffer, buf, n); n -= copy_from_user(temp_buffer, buf, n);
if (!n) {
if (!c)
c = -EFAULT;
break;
}
r = to->ldisc.receive_room(to); r = to->ldisc.receive_room(to);
if (r <= 0) if (r <= 0)
break; break;
...@@ -179,7 +178,7 @@ static void pty_flush_buffer(struct tty_struct *tty) ...@@ -179,7 +178,7 @@ static void pty_flush_buffer(struct tty_struct *tty)
} }
} }
int pty_open(struct tty_struct *tty, struct file * filp) static int pty_open(struct tty_struct *tty, struct file * filp)
{ {
int retval; int retval;
int line; int line;
...@@ -230,6 +229,7 @@ int pty_init(void) ...@@ -230,6 +229,7 @@ int pty_init(void)
memset(&pty_state, 0, sizeof(pty_state)); memset(&pty_state, 0, sizeof(pty_state));
memset(&pty_driver, 0, sizeof(struct tty_driver)); memset(&pty_driver, 0, sizeof(struct tty_driver));
pty_driver.magic = TTY_DRIVER_MAGIC; pty_driver.magic = TTY_DRIVER_MAGIC;
pty_driver.driver_name = "pty_master";
pty_driver.name = "pty"; pty_driver.name = "pty";
pty_driver.major = PTY_MASTER_MAJOR; pty_driver.major = PTY_MASTER_MAJOR;
pty_driver.minor_start = 0; pty_driver.minor_start = 0;
...@@ -258,6 +258,8 @@ int pty_init(void) ...@@ -258,6 +258,8 @@ int pty_init(void)
pty_driver.set_termios = pty_set_termios; pty_driver.set_termios = pty_set_termios;
pty_slave_driver = pty_driver; pty_slave_driver = pty_driver;
pty_slave_driver.driver_name = "pty_slave";
pty_slave_driver.proc_entry = 0;
pty_slave_driver.name = "ttyp"; pty_slave_driver.name = "ttyp";
pty_slave_driver.subtype = PTY_TYPE_SLAVE; pty_slave_driver.subtype = PTY_TYPE_SLAVE;
pty_slave_driver.major = PTY_SLAVE_MAJOR; pty_slave_driver.major = PTY_SLAVE_MAJOR;
...@@ -270,12 +272,16 @@ int pty_init(void) ...@@ -270,12 +272,16 @@ int pty_init(void)
pty_slave_driver.other = &pty_driver; pty_slave_driver.other = &pty_driver;
old_pty_driver = pty_driver; old_pty_driver = pty_driver;
old_pty_driver.driver_name = "compat_pty_master";
old_pty_driver.proc_entry = 0;
old_pty_driver.major = TTY_MAJOR; old_pty_driver.major = TTY_MAJOR;
old_pty_driver.minor_start = 128; old_pty_driver.minor_start = 128;
old_pty_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS; old_pty_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS;
old_pty_driver.other = &old_pty_slave_driver; old_pty_driver.other = &old_pty_slave_driver;
old_pty_slave_driver = pty_slave_driver; old_pty_slave_driver = pty_slave_driver;
old_pty_slave_driver.driver_name = "compat_pty_slave";
old_pty_slave_driver.proc_entry = 0;
old_pty_slave_driver.major = TTY_MAJOR; old_pty_slave_driver.major = TTY_MAJOR;
old_pty_slave_driver.minor_start = 192; old_pty_slave_driver.minor_start = 192;
old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS; old_pty_slave_driver.num = (NR_PTYS > 64) ? 64 : NR_PTYS;
......
/* /*
* random.c -- A strong random number generator * random.c -- A strong random number generator
* *
* Version 1.00, last modified 26-May-96 * Version 1.01, last modified 13-Feb-97
* *
* Copyright Theodore Ts'o, 1994, 1995, 1996. All rights reserved. * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
...@@ -268,6 +268,21 @@ ...@@ -268,6 +268,21 @@
#error No primitive polynomial available for chosen POOLWORDS #error No primitive polynomial available for chosen POOLWORDS
#endif #endif
/*
* For the purposes of better mixing, we use the CRC-32 polynomial as
* well to make a twisted Generalized Feedback Shift Reigster
*
* (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM
* Transactions on Modeling and Computer Simulation 2(3):179-194.
* Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators
* II. ACM Transactions on Mdeling and Computer Simulation 4:254-266)
*
* Thanks to Colin Plumb for suggesting this. (Note that the behavior
* of the 1.0 version of the driver was equivalent to using a second
* element of 0x80000000).
*/
static __u32 twist_table[2] = { 0, 0xEDB88320 };
/* /*
* The minimum number of bits to release a "wait on input". Should * The minimum number of bits to release a "wait on input". Should
* probably always be 8, since a /dev/random read can return a single * probably always be 8, since a /dev/random read can return a single
...@@ -287,7 +302,7 @@ struct random_bucket { ...@@ -287,7 +302,7 @@ struct random_bucket {
unsigned add_ptr; unsigned add_ptr;
unsigned entropy_count; unsigned entropy_count;
int input_rotate; int input_rotate;
__u32 *pool; __u32 pool[POOLWORDS];
}; };
#ifdef RANDOM_BENCHMARK #ifdef RANDOM_BENCHMARK
...@@ -321,13 +336,13 @@ struct timer_rand_state { ...@@ -321,13 +336,13 @@ struct timer_rand_state {
}; };
static struct random_bucket random_state; static struct random_bucket random_state;
static __u32 random_pool[POOLWORDS];
static struct timer_rand_state keyboard_timer_state; static struct timer_rand_state keyboard_timer_state;
static struct timer_rand_state mouse_timer_state; static struct timer_rand_state mouse_timer_state;
static struct timer_rand_state extract_timer_state; static struct timer_rand_state extract_timer_state;
static struct timer_rand_state *irq_timer_state[NR_IRQS]; static struct timer_rand_state *irq_timer_state[NR_IRQS];
static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV]; static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV];
static struct wait_queue *random_wait; static struct wait_queue *random_read_wait;
static struct wait_queue *random_write_wait;
static long random_read(struct inode * inode, struct file * file, static long random_read(struct inode * inode, struct file * file,
char * buf, unsigned long nbytes); char * buf, unsigned long nbytes);
...@@ -432,11 +447,7 @@ static void init_std_data(struct random_bucket *r) ...@@ -432,11 +447,7 @@ static void init_std_data(struct random_bucket *r)
/* Clear the entropy pool and associated counters. */ /* Clear the entropy pool and associated counters. */
static void rand_clear_pool(void) static void rand_clear_pool(void)
{ {
random_state.add_ptr = 0; memset(&random_state, 0, sizeof(random_state));
random_state.entropy_count = 0;
random_state.pool = random_pool;
random_state.input_rotate = 0;
memset(random_pool, 0, sizeof(random_pool));
init_std_data(&random_state); init_std_data(&random_state);
} }
...@@ -456,7 +467,8 @@ void rand_initialize(void) ...@@ -456,7 +467,8 @@ void rand_initialize(void)
initialize_benchmark(&timer_benchmark, "timer", 0); initialize_benchmark(&timer_benchmark, "timer", 0);
#endif #endif
extract_timer_state.dont_count_entropy = 1; extract_timer_state.dont_count_entropy = 1;
random_wait = NULL; random_read_wait = NULL;
random_write_wait = NULL;
} }
void rand_initialize_irq(int irq) void rand_initialize_irq(int irq)
...@@ -516,8 +528,6 @@ static inline void fast_add_entropy_word(struct random_bucket *r, ...@@ -516,8 +528,6 @@ static inline void fast_add_entropy_word(struct random_bucket *r,
int new_rotate; int new_rotate;
__u32 w; __u32 w;
w = rotate_left(r->input_rotate, input);
i = r->add_ptr = (r->add_ptr - 1) & (POOLWORDS-1);
/* /*
* Normally, we add 7 bits of rotation to the pool. At the * Normally, we add 7 bits of rotation to the pool. At the
* beginning of the pool, add an extra 7 bits rotation, so * beginning of the pool, add an extra 7 bits rotation, so
...@@ -525,19 +535,21 @@ static inline void fast_add_entropy_word(struct random_bucket *r, ...@@ -525,19 +535,21 @@ static inline void fast_add_entropy_word(struct random_bucket *r,
* pool evenly. * pool evenly.
*/ */
new_rotate = r->input_rotate + 14; new_rotate = r->input_rotate + 14;
if (i) if ((i = r->add_ptr--))
new_rotate = r->input_rotate + 7; new_rotate -= 7;
r->input_rotate = new_rotate & 31; r->input_rotate = new_rotate & 31;
w = rotate_left(r->input_rotate, input);
/* XOR in the various taps */ /* XOR in the various taps */
w ^= r->pool[(i+TAP1)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP1)&(POOLWORDS-1)];
w ^= r->pool[(i+TAP2)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP2)&(POOLWORDS-1)];
w ^= r->pool[(i+TAP3)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP3)&(POOLWORDS-1)];
w ^= r->pool[(i+TAP4)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP4)&(POOLWORDS-1)];
w ^= r->pool[(i+TAP5)&(POOLWORDS-1)]; w ^= r->pool[(i+TAP5)&(POOLWORDS-1)];
w ^= r->pool[i]; w ^= r->pool[i&(POOLWORDS-1)];
/* Rotate w left 1 bit (stolen from SHA) and store */ /* Use a twisted GFSR for the mixing operation */
r->pool[i] = (w << 1) | (w >> 31); r->pool[i&(POOLWORDS-1)] = (w >> 1) ^ twist_table[w & 1];
} }
/* /*
...@@ -619,7 +631,7 @@ static void add_timer_randomness(struct random_bucket *r, ...@@ -619,7 +631,7 @@ static void add_timer_randomness(struct random_bucket *r,
/* Wake up waiting processes, if we have enough entropy. */ /* Wake up waiting processes, if we have enough entropy. */
if (r->entropy_count >= WAIT_INPUT_BITS) if (r->entropy_count >= WAIT_INPUT_BITS)
wake_up_interruptible(&random_wait); wake_up_interruptible(&random_read_wait);
#ifdef RANDOM_BENCHMARK #ifdef RANDOM_BENCHMARK
end_benchmark(&timer_benchmark); end_benchmark(&timer_benchmark);
#endif #endif
...@@ -662,6 +674,8 @@ void add_blkdev_randomness(int major) ...@@ -662,6 +674,8 @@ void add_blkdev_randomness(int major)
#ifdef USE_SHA #ifdef USE_SHA
#define SMALL_VERSION /* Optimize for space over time */
#define HASH_BUFFER_SIZE 5 #define HASH_BUFFER_SIZE 5
#define HASH_TRANSFORM SHATransform #define HASH_TRANSFORM SHATransform
...@@ -694,10 +708,14 @@ void add_blkdev_randomness(int major) ...@@ -694,10 +708,14 @@ void add_blkdev_randomness(int major)
( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
void SHATransform(__u32 *digest, __u32 *data) static void SHATransform(__u32 *digest, __u32 *data)
{ {
__u32 A, B, C, D, E; /* Local vars */ __u32 A, B, C, D, E; /* Local vars */
__u32 eData[ 16 ]; /* Expanded data */ __u32 eData[ 16 ]; /* Expanded data */
#ifdef SMALL_VERSION
int i;
__u32 TEMP;
#endif
/* Set up first buffer and local data buffer */ /* Set up first buffer and local data buffer */
A = digest[ 0 ]; A = digest[ 0 ];
...@@ -707,6 +725,25 @@ void SHATransform(__u32 *digest, __u32 *data) ...@@ -707,6 +725,25 @@ void SHATransform(__u32 *digest, __u32 *data)
E = digest[ 4 ]; E = digest[ 4 ];
memcpy( eData, data, 16*sizeof(__u32)); memcpy( eData, data, 16*sizeof(__u32));
#ifdef SMALL_VERSION
/*
* Approximately 50% of the speed of the optimized version, but
* takes up 1/16 the space. Saves about 6k on an i386 kernel.
*/
for (i=0; i < 80; i++) {
if (i < 20)
TEMP = f1(B, C, D) + K1;
else if (i < 40)
TEMP = f2(B, C, D) + K2;
else if (i < 60)
TEMP = f3(B, C, D) + K3;
else
TEMP = f4(B, C, D) + K4;
TEMP += ROTL (5, A) + E +
((i > 15) ? expand(eData, i) : eData[i]);
E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
}
#else
/* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 0 ] );
subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 1 ] );
...@@ -791,6 +828,7 @@ void SHATransform(__u32 *digest, __u32 *data) ...@@ -791,6 +828,7 @@ void SHATransform(__u32 *digest, __u32 *data)
subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) );
subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) );
subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );
#endif /* SMALL_VERSION */
/* Build message digest */ /* Build message digest */
digest[ 0 ] += A; digest[ 0 ] += A;
...@@ -938,12 +976,6 @@ static int extract_entropy(struct random_bucket *r, char * buf, ...@@ -938,12 +976,6 @@ static int extract_entropy(struct random_bucket *r, char * buf,
__u32 tmp[HASH_BUFFER_SIZE]; __u32 tmp[HASH_BUFFER_SIZE];
char *cp,*dp; char *cp,*dp;
if (to_user) {
ret = verify_area(VERIFY_WRITE, (void *) buf, nbytes);
if (ret)
return(ret);
}
add_timer_randomness(r, &extract_timer_state, nbytes); add_timer_randomness(r, &extract_timer_state, nbytes);
/* Redundant, but just in case... */ /* Redundant, but just in case... */
...@@ -956,6 +988,9 @@ static int extract_entropy(struct random_bucket *r, char * buf, ...@@ -956,6 +988,9 @@ static int extract_entropy(struct random_bucket *r, char * buf,
else else
r->entropy_count = 0; r->entropy_count = 0;
if (r->entropy_count < WAIT_OUTPUT_BITS)
wake_up_interruptible(&random_write_wait);
while (nbytes) { while (nbytes) {
/* Hash the pool to get the output */ /* Hash the pool to get the output */
tmp[0] = 0x67452301; tmp[0] = 0x67452301;
...@@ -995,9 +1030,13 @@ static int extract_entropy(struct random_bucket *r, char * buf, ...@@ -995,9 +1030,13 @@ static int extract_entropy(struct random_bucket *r, char * buf,
/* Copy data to destination buffer */ /* Copy data to destination buffer */
i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2); i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
if (to_user) if (to_user) {
copy_to_user(buf, (__u8 const *)tmp, i); i -= copy_to_user(buf, (__u8 const *)tmp, i);
else if (!i) {
ret = -EFAULT;
break;
}
} else
memcpy(buf, (__u8 const *)tmp, i); memcpy(buf, (__u8 const *)tmp, i);
nbytes -= i; nbytes -= i;
buf += i; buf += i;
...@@ -1033,7 +1072,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long ...@@ -1033,7 +1072,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long
if (nbytes == 0) if (nbytes == 0)
return 0; return 0;
add_wait_queue(&random_wait, &wait); add_wait_queue(&random_read_wait, &wait);
while (nbytes > 0) { while (nbytes > 0) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
...@@ -1065,7 +1104,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long ...@@ -1065,7 +1104,7 @@ random_read(struct inode * inode, struct file * file, char * buf, unsigned long
/* like a named pipe */ /* like a named pipe */
} }
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
remove_wait_queue(&random_wait, &wait); remove_wait_queue(&random_read_wait, &wait);
/* /*
* If we gave the user some bytes and we have an inode pointer, * If we gave the user some bytes and we have an inode pointer,
...@@ -1091,9 +1130,10 @@ random_poll(struct file *file, poll_table * wait) ...@@ -1091,9 +1130,10 @@ random_poll(struct file *file, poll_table * wait)
{ {
unsigned int mask; unsigned int mask;
poll_wait(&random_wait, wait); poll_wait(&random_read_wait, wait);
poll_wait(&random_write_wait, wait);
mask = 0; mask = 0;
if (random_state.entropy_count >= 8) if (random_state.entropy_count >= WAIT_INPUT_BITS)
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
if (random_state.entropy_count < WAIT_OUTPUT_BITS) if (random_state.entropy_count < WAIT_OUTPUT_BITS)
mask |= POLLOUT | POLLWRNORM; mask |= POLLOUT | POLLWRNORM;
...@@ -1104,25 +1144,33 @@ static long ...@@ -1104,25 +1144,33 @@ static long
random_write(struct inode * inode, struct file * file, random_write(struct inode * inode, struct file * file,
const char * buffer, unsigned long count) const char * buffer, unsigned long count)
{ {
int i; int i, bytes, ret = 0;
__u32 word, *p; __u32 buf[16];
const char *p = buffer;
for (i = count, p = (__u32 *)buffer; int c = count;
i >= sizeof(__u32);
i-= sizeof(__u32), p++) { while (c > 0) {
copy_from_user(&word, p, sizeof(__u32)); bytes = MIN(c, sizeof(buf));
add_entropy_word(&random_state, word);
bytes -= copy_from_user(&buf, p, bytes);
if (!bytes) {
if (!ret)
ret = -EFAULT;
break;
} }
if (i) { c -= bytes;
word = 0; p += bytes;
copy_from_user(&word, p, i); ret += bytes;
add_entropy_word(&random_state, word);
i = (c+sizeof(__u32)-1) / sizeof(__u32);
while (i--)
add_entropy_word(&random_state, buf[i]);
} }
if (inode) { if ((ret > 0) && inode) {
inode->i_mtime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME;
inode->i_dirt = 1; inode->i_dirt = 1;
} }
return count; return ret;
} }
static int static int
...@@ -1132,20 +1180,6 @@ random_ioctl(struct inode * inode, struct file * file, ...@@ -1132,20 +1180,6 @@ random_ioctl(struct inode * inode, struct file * file,
int *p, size, ent_count; int *p, size, ent_count;
int retval; int retval;
/*
* Translate old 1.3.XX values.
* Remove this code in 2.1.0.
* <mec@duracef.shout.net>
*/
switch (cmd) {
case 0x01080000: cmd = RNDGETENTCNT; break;
case 0x01080001: cmd = RNDADDTOENTCNT; break;
case 0x01080002: cmd = RNDGETPOOL; break;
case 0x01080003: cmd = RNDADDENTROPY; break;
case 0x01080004: cmd = RNDZAPENTCNT; break;
case 0x01080006: cmd = RNDCLEARPOOL; break;
}
switch (cmd) { switch (cmd) {
case RNDGETENTCNT: case RNDGETENTCNT:
retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); retval = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
...@@ -1181,7 +1215,7 @@ random_ioctl(struct inode * inode, struct file * file, ...@@ -1181,7 +1215,7 @@ random_ioctl(struct inode * inode, struct file * file,
* entropy. * entropy.
*/ */
if (random_state.entropy_count >= WAIT_INPUT_BITS) if (random_state.entropy_count >= WAIT_INPUT_BITS)
wake_up_interruptible(&random_wait); wake_up_interruptible(&random_read_wait);
return 0; return 0;
case RNDGETPOOL: case RNDGETPOOL:
if (!suser()) if (!suser())
...@@ -1201,11 +1235,8 @@ random_ioctl(struct inode * inode, struct file * file, ...@@ -1201,11 +1235,8 @@ random_ioctl(struct inode * inode, struct file * file,
return -EINVAL; return -EINVAL;
if (size > POOLWORDS) if (size > POOLWORDS)
size = POOLWORDS; size = POOLWORDS;
retval = verify_area(VERIFY_WRITE, (void *) p, if (copy_to_user(p, random_state.pool, size*sizeof(__u32)))
size * sizeof(__u32)); return -EFAULT;
if (retval)
return retval;
copy_to_user(p, random_state.pool, size*sizeof(__u32));
return 0; return 0;
case RNDADDENTROPY: case RNDADDENTROPY:
if (!suser()) if (!suser())
...@@ -1242,7 +1273,7 @@ random_ioctl(struct inode * inode, struct file * file, ...@@ -1242,7 +1273,7 @@ random_ioctl(struct inode * inode, struct file * file,
* entropy. * entropy.
*/ */
if (random_state.entropy_count >= WAIT_INPUT_BITS) if (random_state.entropy_count >= WAIT_INPUT_BITS)
wake_up_interruptible(&random_wait); wake_up_interruptible(&random_read_wait);
return 0; return 0;
case RNDZAPENTCNT: case RNDZAPENTCNT:
if (!suser()) if (!suser())
......
...@@ -19,10 +19,12 @@ ...@@ -19,10 +19,12 @@
* flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
* Bernd Anhupl 05/17/96. * Bernd Anhupl 05/17/96.
* *
* 1/97: Extended dumb serial ports are a config option now.
* Saves 4k. Michael A. Griffith <grif@acm.org>
*
* This module exports the following rs232 io functions: * This module exports the following rs232 io functions:
* *
* int rs_init(void); * int rs_init(void);
* int rs_open(struct tty_struct * tty, struct file * filp)
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -50,17 +52,13 @@ ...@@ -50,17 +52,13 @@
#include <asm/bitops.h> #include <asm/bitops.h>
static char *serial_name = "Serial driver"; static char *serial_name = "Serial driver";
static char *serial_version = "4.22"; static char *serial_version = "4.23";
DECLARE_TASK_QUEUE(tq_serial); static DECLARE_TASK_QUEUE(tq_serial);
struct tty_driver serial_driver, callout_driver; static struct tty_driver serial_driver, callout_driver;
static int serial_refcount; static int serial_refcount;
/* serial subtype definitions */
#define SERIAL_TYPE_NORMAL 1
#define SERIAL_TYPE_CALLOUT 2
/* number of characters left in xmit buffer before we ask for more */ /* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256 #define WAKEUP_CHARS 256
...@@ -71,6 +69,16 @@ static int serial_refcount; ...@@ -71,6 +69,16 @@ static int serial_refcount;
* Enables support for the venerable Bell Technologies * Enables support for the venerable Bell Technologies
* HUB6 card. * HUB6 card.
* *
* CONFIG_SERIAL_MANY_PORTS
* Enables support for ports beyond the standard, stupid
* COM 1/2/3/4.
*
* CONFIG_SERIAL_MULTIPORT
* Enables support for special multiport board support.
*
* CONFIG_SERIAL_SHARE_IRQ
* Enables support for multiple serial ports on one IRQ
*
* SERIAL_PARANOIA_CHECK * SERIAL_PARANOIA_CHECK
* Check the magic number for the async_structure where * Check the magic number for the async_structure where
* ever possible. * ever possible.
...@@ -80,6 +88,34 @@ static int serial_refcount; ...@@ -80,6 +88,34 @@ static int serial_refcount;
#define CONFIG_SERIAL_NOPAUSE_IO #define CONFIG_SERIAL_NOPAUSE_IO
#define SERIAL_DO_RESTART #define SERIAL_DO_RESTART
#if 0
/* Normally these defines are controlled by the autoconf.h */
#define CONFIG_SERIAL_MANY_PORTS
#define CONFIG_SERIAL_SHARE_IRQ
#define CONFIG_SERIAL_MULTIPORT
#define CONFIG_HUB6
#endif
/* Sanity checks */
#ifdef CONFIG_SERIAL_MULTIPORT
#ifndef CONFIG_SERIAL_SHARE_IRQ
#define CONFIG_SERIAL_SHARE_IRQ
#endif
#endif
#ifdef CONFIG_HUB6
#ifndef CONFIG_SERIAL_MANY_PORTS
#define CONFIG_SERIAL_MANY_PORTS
#endif
#ifndef CONFIG_SERIAL_SHARE_IRQ
#define CONFIG_SERIAL_SHARE_IRQ
#endif
#endif
/* Set of debugging defines */
#undef SERIAL_DEBUG_INTR #undef SERIAL_DEBUG_INTR
#undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW #undef SERIAL_DEBUG_FLOW
...@@ -105,7 +141,9 @@ static int serial_refcount; ...@@ -105,7 +141,9 @@ static int serial_refcount;
*/ */
static struct async_struct *IRQ_ports[16]; static struct async_struct *IRQ_ports[16];
#ifdef CONFIG_SERIAL_MULTIPORT
static struct rs_multiport_struct rs_multiport[16]; static struct rs_multiport_struct rs_multiport[16];
#endif
static int IRQ_timeout[16]; static int IRQ_timeout[16];
static volatile int rs_irq_triggered; static volatile int rs_irq_triggered;
static volatile int rs_triggered; static volatile int rs_triggered;
...@@ -146,10 +184,13 @@ static struct serial_uart_config uart_config[] = { ...@@ -146,10 +184,13 @@ static struct serial_uart_config uart_config[] = {
#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 #define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
#ifdef CONFIG_SERIAL_MANY_PORTS
#define FOURPORT_FLAGS ASYNC_FOURPORT #define FOURPORT_FLAGS ASYNC_FOURPORT
#define ACCENT_FLAGS 0 #define ACCENT_FLAGS 0
#define BOCA_FLAGS 0 #define BOCA_FLAGS 0
#define HUB6_FLAGS 0 #define HUB6_FLAGS 0
#endif
/* /*
* The following define the access methods for the HUB6 card. All * The following define the access methods for the HUB6 card. All
...@@ -167,13 +208,13 @@ static struct serial_uart_config uart_config[] = { ...@@ -167,13 +208,13 @@ static struct serial_uart_config uart_config[] = {
#define C_P(card,port) (((card)<<6|(port)<<3) + 1) #define C_P(card,port) (((card)<<6|(port)<<3) + 1)
struct serial_state rs_table[] = { static struct serial_state rs_table[] = {
/* UART CLK PORT IRQ FLAGS */ /* UART CLK PORT IRQ FLAGS */
{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */
{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */
{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */
{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
#ifdef CONFIG_SERIAL_MANY_PORTS
{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */
{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */
{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */
...@@ -223,6 +264,7 @@ struct serial_state rs_table[] = { ...@@ -223,6 +264,7 @@ struct serial_state rs_table[] = {
{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */
{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */
#endif #endif
#endif /* CONFIG_SERIAL_MANY_PORTS */
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
{ 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS }, { 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS },
{ 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS }, { 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS },
...@@ -426,43 +468,79 @@ static _INLINE_ void receive_chars(struct async_struct *info, ...@@ -426,43 +468,79 @@ static _INLINE_ void receive_chars(struct async_struct *info,
struct tty_struct *tty = info->tty; struct tty_struct *tty = info->tty;
unsigned char ch; unsigned char ch;
int ignored = 0; int ignored = 0;
struct async_icount *icount;
icount = &info->state->icount;
do { do {
ch = serial_inp(info, UART_RX); ch = serial_inp(info, UART_RX);
if (*status & UART_LSR_BI) if (tty->flip.count >= TTY_FLIPBUF_SIZE)
break;
*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 & (UART_LSR_BI | UART_LSR_PE |
UART_LSR_FE | UART_LSR_OE)) {
/*
* For statistics only
*/
if (*status & UART_LSR_BI) {
*status &= ~(UART_LSR_FE | UART_LSR_PE); *status &= ~(UART_LSR_FE | UART_LSR_PE);
icount->brk++;
} else if (*status & UART_LSR_PE)
icount->parity++;
else if (*status & UART_LSR_FE)
icount->frame++;
if (*status & UART_LSR_OE)
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 (*status & info->ignore_status_mask) {
if (++ignored > 100) if (++ignored > 100)
break; break;
goto ignore_char; goto ignore_char;
} }
*status &= info->read_status_mask; *status &= info->read_status_mask;
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
break;
tty->flip.count++;
if (*status & (UART_LSR_BI)) { if (*status & (UART_LSR_BI)) {
#ifdef SERIAL_DEBUG_INTR #ifdef SERIAL_DEBUG_INTR
printk("handling break...."); printk("handling break....");
#endif #endif
*tty->flip.flag_buf_ptr++ = TTY_BREAK; *tty->flip.flag_buf_ptr = TTY_BREAK;
if (info->flags & ASYNC_SAK) if (info->flags & ASYNC_SAK)
do_SAK(tty); do_SAK(tty);
} else if (*status & UART_LSR_PE) } else if (*status & UART_LSR_PE)
*tty->flip.flag_buf_ptr++ = TTY_PARITY; *tty->flip.flag_buf_ptr = TTY_PARITY;
else if (*status & UART_LSR_FE) else if (*status & UART_LSR_FE)
*tty->flip.flag_buf_ptr++ = TTY_FRAME; *tty->flip.flag_buf_ptr = TTY_FRAME;
else if (*status & UART_LSR_OE) if (*status & UART_LSR_OE) {
*tty->flip.flag_buf_ptr++ = TTY_OVERRUN; /*
else * Overrun is special, since it's
*tty->flip.flag_buf_ptr++ = 0; * reported immediately, and doesn't
*tty->flip.char_buf_ptr++ = ch; * 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;
}
}
}
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
ignore_char: ignore_char:
*status = serial_inp(info, UART_LSR); *status = serial_inp(info, UART_LSR);
} while (*status & UART_LSR_DR); } while (*status & UART_LSR_DR);
queue_task_irq_off(&tty->flip.tqueue, &tq_timer); queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
#ifdef SERIAL_DEBUG_INTR
printk("DR...");
#endif
} }
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
...@@ -471,6 +549,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -471,6 +549,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
if (info->x_char) { if (info->x_char) {
serial_outp(info, UART_TX, info->x_char); serial_outp(info, UART_TX, info->x_char);
info->state->icount.tx++;
info->x_char = 0; info->x_char = 0;
if (intr_done) if (intr_done)
*intr_done = 0; *intr_done = 0;
...@@ -487,6 +566,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -487,6 +566,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
do { do {
serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]); serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]);
info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
info->state->icount.tx++;
if (--info->xmit_cnt <= 0) if (--info->xmit_cnt <= 0)
break; break;
} while (--count > 0); } while (--count > 0);
...@@ -574,6 +654,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info) ...@@ -574,6 +654,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
} }
} }
#ifdef CONFIG_SERIAL_SHARE_IRQ
/* /*
* This is the serial driver's generic interrupt routine * This is the serial driver's generic interrupt routine
*/ */
...@@ -583,8 +664,10 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -583,8 +664,10 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
struct async_struct * info; struct async_struct * info;
int pass_counter = 0; int pass_counter = 0;
struct async_struct *end_mark = 0; struct async_struct *end_mark = 0;
#ifdef CONFIG_SERIAL_MULTIPORT
int first_multi = 0; int first_multi = 0;
struct rs_multiport_struct *multi; struct rs_multiport_struct *multi;
#endif
#ifdef SERIAL_DEBUG_INTR #ifdef SERIAL_DEBUG_INTR
printk("rs_interrupt(%d)...", irq); printk("rs_interrupt(%d)...", irq);
...@@ -594,9 +677,11 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -594,9 +677,11 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (!info) if (!info)
return; return;
#ifdef CONFIG_SERIAL_MULTIPORT
multi = &rs_multiport[irq]; multi = &rs_multiport[irq];
if (multi->port_monitor) if (multi->port_monitor)
first_multi = inb(multi->port_monitor); first_multi = inb(multi->port_monitor);
#endif
do { do {
if (!info->tty || if (!info->tty ||
...@@ -632,14 +717,18 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -632,14 +717,18 @@ static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
continue; continue;
} }
} while (end_mark != info); } while (end_mark != info);
#ifdef CONFIG_SERIAL_MULTIPORT
if (multi->port_monitor) if (multi->port_monitor)
printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n",
info->state->irq, first_multi, info->state->irq, first_multi,
inb(multi->port_monitor)); inb(multi->port_monitor));
#endif
#ifdef SERIAL_DEBUG_INTR #ifdef SERIAL_DEBUG_INTR
printk("end.\n"); printk("end.\n");
#endif #endif
} }
#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */
/* /*
* This is the serial driver's interrupt routine for a single port * This is the serial driver's interrupt routine for a single port
...@@ -648,9 +737,11 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) ...@@ -648,9 +737,11 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
{ {
int status; int status;
int pass_counter = 0; int pass_counter = 0;
int first_multi = 0;
struct async_struct * info; struct async_struct * info;
#ifdef CONFIG_SERIAL_MULTIPORT
int first_multi = 0;
struct rs_multiport_struct *multi; struct rs_multiport_struct *multi;
#endif
#ifdef SERIAL_DEBUG_INTR #ifdef SERIAL_DEBUG_INTR
printk("rs_interrupt_single(%d)...", irq); printk("rs_interrupt_single(%d)...", irq);
...@@ -660,9 +751,11 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) ...@@ -660,9 +751,11 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
if (!info || !info->tty) if (!info || !info->tty)
return; return;
#ifdef CONFIG_SERIAL_MULTIPORT
multi = &rs_multiport[irq]; multi = &rs_multiport[irq];
if (multi->port_monitor) if (multi->port_monitor)
first_multi = inb(multi->port_monitor); first_multi = inb(multi->port_monitor);
#endif
do { do {
status = serial_inp(info, UART_LSR); status = serial_inp(info, UART_LSR);
...@@ -682,15 +775,18 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) ...@@ -682,15 +775,18 @@ static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
} }
} while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT));
info->last_active = jiffies; info->last_active = jiffies;
#ifdef CONFIG_SERIAL_MULTIPORT
if (multi->port_monitor) if (multi->port_monitor)
printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n",
info->state->irq, first_multi, info->state->irq, first_multi,
inb(multi->port_monitor)); inb(multi->port_monitor));
#endif
#ifdef SERIAL_DEBUG_INTR #ifdef SERIAL_DEBUG_INTR
printk("end.\n"); printk("end.\n");
#endif #endif
} }
#ifdef CONFIG_SERIAL_MULTIPORT
/* /*
* This is the serial driver's for multiport boards * This is the serial driver's for multiport boards
*/ */
...@@ -771,7 +867,7 @@ static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs) ...@@ -771,7 +867,7 @@ static void rs_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs)
printk("end.\n"); printk("end.\n");
#endif #endif
} }
#endif
/* /*
* ------------------------------------------------------------------- * -------------------------------------------------------------------
...@@ -851,6 +947,7 @@ static void rs_timer(void) ...@@ -851,6 +947,7 @@ static void rs_timer(void)
if (!info) if (!info)
continue; continue;
cli(); cli();
#ifdef CONFIG_SERIAL_SHARE_IRQ
if (info->next_port) { if (info->next_port) {
do { do {
serial_out(info, UART_IER, 0); serial_out(info, UART_IER, 0);
...@@ -858,11 +955,14 @@ static void rs_timer(void) ...@@ -858,11 +955,14 @@ static void rs_timer(void)
serial_out(info, UART_IER, info->IER); serial_out(info, UART_IER, info->IER);
info = info->next_port; info = info->next_port;
} while (info); } while (info);
#ifdef CONFIG_SERIAL_MULTIPORT
if (rs_multiport[i].port1) if (rs_multiport[i].port1)
rs_interrupt_multi(i, NULL, NULL); rs_interrupt_multi(i, NULL, NULL);
else else
#endif
rs_interrupt(i, NULL, NULL); rs_interrupt(i, NULL, NULL);
} else } else
#endif /* CONFIG_SERIAL_SHARE_IRQ */
rs_interrupt_single(i, NULL, NULL); rs_interrupt_single(i, NULL, NULL);
sti(); sti();
} }
...@@ -873,7 +973,11 @@ static void rs_timer(void) ...@@ -873,7 +973,11 @@ static void rs_timer(void)
if (IRQ_ports[0]) { if (IRQ_ports[0]) {
cli(); cli();
#ifdef CONFIG_SERIAL_SHARE_IRQ
rs_interrupt(0, NULL, NULL); rs_interrupt(0, NULL, NULL);
#else
rs_interrupt_single(0, NULL, NULL);
#endif
sti(); sti();
timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2; timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
...@@ -948,12 +1052,15 @@ static void figure_IRQ_timeout(int irq) ...@@ -948,12 +1052,15 @@ static void figure_IRQ_timeout(int irq)
static int startup(struct async_struct * info) static int startup(struct async_struct * info)
{ {
unsigned short ICP;
unsigned long flags; unsigned long flags;
int retval; int retval;
void (*handler)(int, void *, struct pt_regs *); void (*handler)(int, void *, struct pt_regs *);
struct serial_state *state= info->state; struct serial_state *state= info->state;
unsigned long page; unsigned long page;
#ifdef CONFIG_SERIAL_MANY_PORTS
unsigned short ICP;
#endif
page = get_free_page(GFP_KERNEL); page = get_free_page(GFP_KERNEL);
if (!page) if (!page)
...@@ -1026,11 +1133,17 @@ static int startup(struct async_struct * info) ...@@ -1026,11 +1133,17 @@ static int startup(struct async_struct * info)
if (state->irq && (!IRQ_ports[state->irq] || if (state->irq && (!IRQ_ports[state->irq] ||
!IRQ_ports[state->irq]->next_port)) { !IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) { if (IRQ_ports[state->irq]) {
#ifdef CONFIG_SERIAL_SHARE_IRQ
free_irq(state->irq, NULL); free_irq(state->irq, NULL);
#ifdef CONFIG_SERIAL_MULTIPORT
if (rs_multiport[state->irq].port1) if (rs_multiport[state->irq].port1)
handler = rs_interrupt_multi; handler = rs_interrupt_multi;
else else
#endif
handler = rs_interrupt; handler = rs_interrupt;
#else
return -EBUSY;
#endif /* CONFIG_SERIAL_SHARE_IRQ */
} else } else
handler = rs_interrupt_single; handler = rs_interrupt_single;
...@@ -1074,10 +1187,13 @@ static int startup(struct async_struct * info) ...@@ -1074,10 +1187,13 @@ static int startup(struct async_struct * info)
info->MCR = 0; info->MCR = 0;
if (info->tty->termios->c_cflag & CBAUD) if (info->tty->termios->c_cflag & CBAUD)
info->MCR = UART_MCR_DTR | UART_MCR_RTS; info->MCR = UART_MCR_DTR | UART_MCR_RTS;
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) { if (info->flags & ASYNC_FOURPORT) {
if (state->irq == 0) if (state->irq == 0)
info->MCR |= UART_MCR_OUT1; info->MCR |= UART_MCR_OUT1;
} else { } else
#endif
{
if (state->irq != 0) if (state->irq != 0)
info->MCR |= UART_MCR_OUT2; info->MCR |= UART_MCR_OUT2;
} }
...@@ -1095,12 +1211,14 @@ static int startup(struct async_struct * info) ...@@ -1095,12 +1211,14 @@ static int startup(struct async_struct * info)
info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
serial_outp(info, UART_IER, info->IER); /* enable interrupts */ serial_outp(info, UART_IER, info->IER); /* enable interrupts */
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) { if (info->flags & ASYNC_FOURPORT) {
/* Enable interrupts on the AST Fourport board */ /* Enable interrupts on the AST Fourport board */
ICP = (info->port & 0xFE0) | 0x01F; ICP = (info->port & 0xFE0) | 0x01F;
outb_p(0x80, ICP); outb_p(0x80, ICP);
(void) inb_p(ICP); (void) inb_p(ICP);
} }
#endif
/* /*
* And clear the interrupt registers again for luck. * And clear the interrupt registers again for luck.
...@@ -1193,11 +1311,13 @@ static void shutdown(struct async_struct * info) ...@@ -1193,11 +1311,13 @@ static void shutdown(struct async_struct * info)
info->IER = 0; info->IER = 0;
serial_outp(info, UART_IER, 0x00); /* disable all intrs */ serial_outp(info, UART_IER, 0x00); /* disable all intrs */
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) { if (info->flags & ASYNC_FOURPORT) {
/* reset interrupts on the AST Fourport board */ /* reset interrupts on the AST Fourport board */
(void) inb((info->port & 0xFE0) | 0x01F); (void) inb((info->port & 0xFE0) | 0x01F);
info->MCR |= UART_MCR_OUT1; info->MCR |= UART_MCR_OUT1;
} else } else
#endif
info->MCR &= ~UART_MCR_OUT2; info->MCR &= ~UART_MCR_OUT2;
#if defined(__alpha__) && !defined(CONFIG_PCI) #if defined(__alpha__) && !defined(CONFIG_PCI)
/* /*
...@@ -1270,6 +1390,10 @@ static void change_speed(struct async_struct *info) ...@@ -1270,6 +1390,10 @@ static void change_speed(struct async_struct *info)
} }
if (!(cflag & PARODD)) if (!(cflag & PARODD))
cval |= UART_LCR_EPAR; cval |= UART_LCR_EPAR;
#ifdef CMSPAR
if (cflag & CMSPAR)
cval |= UART_LCR_SPAR;
#endif
/* Determine divisor based on baud rate */ /* Determine divisor based on baud rate */
i = cflag & CBAUD; i = cflag & CBAUD;
...@@ -1303,6 +1427,7 @@ static void change_speed(struct async_struct *info) ...@@ -1303,6 +1427,7 @@ static void change_speed(struct async_struct *info)
if (!quot) if (!quot)
quot = baud_base / 9600; quot = baud_base / 9600;
} }
info->quot = quot;
info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
info->timeout += HZ/50; /* Add .02 seconds of slop */ info->timeout += HZ/50; /* Add .02 seconds of slop */
...@@ -1376,6 +1501,7 @@ static void change_speed(struct async_struct *info) ...@@ -1376,6 +1501,7 @@ static void change_speed(struct async_struct *info)
if (info->state->type == PORT_16750) if (info->state->type == PORT_16750)
serial_outp(info, UART_FCR, fcr); /* set fcr */ serial_outp(info, UART_FCR, fcr); /* set fcr */
serial_outp(info, UART_LCR, cval); /* reset DLAB */ serial_outp(info, UART_LCR, cval); /* reset DLAB */
if (info->state->type != PORT_16750)
serial_outp(info, UART_FCR, fcr); /* set fcr */ serial_outp(info, UART_FCR, fcr); /* set fcr */
restore_flags(flags); restore_flags(flags);
} }
...@@ -1424,7 +1550,7 @@ static void rs_flush_chars(struct tty_struct *tty) ...@@ -1424,7 +1550,7 @@ static void rs_flush_chars(struct tty_struct *tty)
static int rs_write(struct tty_struct * tty, int from_user, static int rs_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count) const unsigned char *buf, int count)
{ {
int c, total = 0; int c, ret = 0;
struct async_struct *info = (struct async_struct *)tty->driver_data; struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -1445,7 +1571,12 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -1445,7 +1571,12 @@ static int rs_write(struct tty_struct * tty, int from_user,
break; break;
if (from_user) { if (from_user) {
copy_from_user(tmp_buf, buf, c); c -= copy_from_user(tmp_buf, buf, c);
if (!c) {
if (!ret)
ret = -EFAULT;
break;
}
c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head)); SERIAL_XMIT_SIZE - info->xmit_head));
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
...@@ -1456,7 +1587,7 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -1456,7 +1587,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
restore_flags(flags); restore_flags(flags);
buf += c; buf += c;
count -= c; count -= c;
total += c; ret += c;
} }
if (from_user) if (from_user)
up(&tmp_buf_sem); up(&tmp_buf_sem);
...@@ -1466,7 +1597,7 @@ static int rs_write(struct tty_struct * tty, int from_user, ...@@ -1466,7 +1597,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
serial_out(info, UART_IER, info->IER); serial_out(info, UART_IER, info->IER);
} }
restore_flags(flags); restore_flags(flags);
return total; return ret;
} }
static int rs_write_room(struct tty_struct *tty) static int rs_write_room(struct tty_struct *tty)
...@@ -1510,7 +1641,7 @@ static void rs_flush_buffer(struct tty_struct *tty) ...@@ -1510,7 +1641,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
* This function is used to send a high-priority XON/XOFF character to * This function is used to send a high-priority XON/XOFF character to
* the device * the device
*/ */
void rs_send_xchar(struct tty_struct *tty, char ch) static void rs_send_xchar(struct tty_struct *tty, char ch)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct async_struct *info = (struct async_struct *)tty->driver_data;
...@@ -1609,7 +1740,8 @@ static int get_serial_info(struct async_struct * info, ...@@ -1609,7 +1740,8 @@ static int get_serial_info(struct async_struct * info,
tmp.closing_wait = state->closing_wait; tmp.closing_wait = state->closing_wait;
tmp.custom_divisor = state->custom_divisor; tmp.custom_divisor = state->custom_divisor;
tmp.hub6 = state->hub6; tmp.hub6 = state->hub6;
copy_to_user(retinfo,&tmp,sizeof(*retinfo)); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0; return 0;
} }
...@@ -1621,9 +1753,8 @@ static int set_serial_info(struct async_struct * info, ...@@ -1621,9 +1753,8 @@ static int set_serial_info(struct async_struct * info,
unsigned int i,change_irq,change_port; unsigned int i,change_irq,change_port;
int retval = 0; int retval = 0;
if (!new_info) if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT; return -EFAULT;
copy_from_user(&new_serial,new_info,sizeof(new_serial));
state = info->state; state = info->state;
old_state = *state; old_state = *state;
...@@ -1734,8 +1865,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value) ...@@ -1734,8 +1865,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value)
status = serial_in(info, UART_LSR); status = serial_in(info, UART_LSR);
sti(); sti();
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
put_user(result,value); return put_user(result,value);
return 0;
} }
...@@ -1750,12 +1880,15 @@ static int get_modem_info(struct async_struct * info, unsigned int *value) ...@@ -1750,12 +1880,15 @@ static int get_modem_info(struct async_struct * info, unsigned int *value)
sti(); sti();
result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 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_DCD) ? TIOCM_CAR : 0)
| ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
| ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
| ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
put_user(result,value); return put_user(result,value);
return 0;
} }
static int set_modem_info(struct async_struct * info, unsigned int cmd, static int set_modem_info(struct async_struct * info, unsigned int cmd,
...@@ -1773,16 +1906,37 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd, ...@@ -1773,16 +1906,37 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
info->MCR |= UART_MCR_RTS; info->MCR |= UART_MCR_RTS;
if (arg & TIOCM_DTR) if (arg & TIOCM_DTR)
info->MCR |= UART_MCR_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; break;
case TIOCMBIC: case TIOCMBIC:
if (arg & TIOCM_RTS) if (arg & TIOCM_RTS)
info->MCR &= ~UART_MCR_RTS; info->MCR &= ~UART_MCR_RTS;
if (arg & TIOCM_DTR) if (arg & TIOCM_DTR)
info->MCR &= ~UART_MCR_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; break;
case TIOCMSET: case TIOCMSET:
info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) 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) | ((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)); | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
break; break;
default: default:
...@@ -1883,6 +2037,7 @@ static int check_wild_interrupts(int doprint) ...@@ -1883,6 +2037,7 @@ static int check_wild_interrupts(int doprint)
return wild_interrupts; return wild_interrupts;
} }
#ifdef CONFIG_SERIAL_MULTIPORT
static int get_multiport_struct(struct async_struct * info, static int get_multiport_struct(struct async_struct * info,
struct serial_multiport_struct *retinfo) struct serial_multiport_struct *retinfo)
{ {
...@@ -1911,9 +2066,9 @@ static int get_multiport_struct(struct async_struct * info, ...@@ -1911,9 +2066,9 @@ static int get_multiport_struct(struct async_struct * info,
ret.irq = info->state->irq; ret.irq = info->state->irq;
copy_to_user(retinfo,&ret,sizeof(*retinfo)); if (copy_to_user(retinfo,&ret,sizeof(*retinfo)))
return -EFAULT;
return 0; return 0;
} }
static int set_multiport_struct(struct async_struct * info, static int set_multiport_struct(struct async_struct * info,
...@@ -1928,12 +2083,11 @@ static int set_multiport_struct(struct async_struct * info, ...@@ -1928,12 +2083,11 @@ static int set_multiport_struct(struct async_struct * info,
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
if (!in_multi)
return -EFAULT;
state = info->state; state = info->state;
copy_from_user(&new_multi, in_multi, if (copy_from_user(&new_multi, in_multi,
sizeof(struct serial_multiport_struct)); sizeof(struct serial_multiport_struct)))
return -EFAULT;
if (new_multi.irq != state->irq || state->irq == 0 || if (new_multi.irq != state->irq || state->irq == 0 ||
!IRQ_ports[state->irq]) !IRQ_ports[state->irq])
...@@ -1996,6 +2150,7 @@ static int set_multiport_struct(struct async_struct * info, ...@@ -1996,6 +2150,7 @@ static int set_multiport_struct(struct async_struct * info,
return 0; return 0;
} }
#endif
static int rs_ioctl(struct tty_struct *tty, struct file * file, static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
...@@ -2053,82 +2208,52 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2053,82 +2208,52 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
(arg ? CLOCAL : 0)); (arg ? CLOCAL : 0));
return 0; return 0;
case TIOCMGET: case TIOCMGET:
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(unsigned int));
if (error)
return error;
return get_modem_info(info, (unsigned int *) arg); return get_modem_info(info, (unsigned int *) arg);
case TIOCMBIS: case TIOCMBIS:
case TIOCMBIC: case TIOCMBIC:
case TIOCMSET: case TIOCMSET:
return set_modem_info(info, cmd, (unsigned int *) arg); return set_modem_info(info, cmd, (unsigned int *) arg);
case TIOCGSERIAL: case TIOCGSERIAL:
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_struct));
if (error)
return error;
return get_serial_info(info, return get_serial_info(info,
(struct serial_struct *) arg); (struct serial_struct *) arg);
case TIOCSSERIAL: case TIOCSSERIAL:
error = verify_area(VERIFY_READ, (void *) arg,
sizeof(struct serial_struct));
if (error)
return error;
return set_serial_info(info, return set_serial_info(info,
(struct serial_struct *) arg); (struct serial_struct *) arg);
case TIOCSERCONFIG: case TIOCSERCONFIG:
return do_autoconfig(info); return do_autoconfig(info);
case TIOCSERGWILD: case TIOCSERGWILD:
error = verify_area(VERIFY_WRITE, (void *) arg, return put_user(rs_wild_int_mask,
sizeof(int)); (unsigned int *) arg);
if (error)
return error;
put_user(rs_wild_int_mask, (unsigned int *) arg);
return 0;
case TIOCSERGETLSR: /* Get line status register */ case TIOCSERGETLSR: /* Get line status register */
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(unsigned int));
if (error)
return error;
else
return get_lsr_info(info, (unsigned int *) arg); return get_lsr_info(info, (unsigned int *) arg);
case TIOCSERSWILD: case TIOCSERSWILD:
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
error = verify_area(VERIFY_READ, (void *) arg,sizeof(long)); error = get_user(rs_wild_int_mask,
(unsigned int *) arg);
if (error) if (error)
return error; return error;
get_user(rs_wild_int_mask, (unsigned int *) arg);
if (rs_wild_int_mask < 0) if (rs_wild_int_mask < 0)
rs_wild_int_mask = check_wild_interrupts(0); rs_wild_int_mask = check_wild_interrupts(0);
return 0; return 0;
case TIOCSERGSTRUCT: case TIOCSERGSTRUCT:
error = verify_area(VERIFY_WRITE, (void *) arg, if (copy_to_user((struct async_struct *) arg,
sizeof(struct async_struct)); info, sizeof(struct async_struct)))
if (error) return -EFAULT;
return error;
copy_to_user((struct async_struct *) arg,
info, sizeof(struct async_struct));
return 0; return 0;
#ifdef CONFIG_SERIAL_MULTIPORT
case TIOCSERGETMULTI: case TIOCSERGETMULTI:
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_multiport_struct));
if (error)
return error;
return get_multiport_struct(info, return get_multiport_struct(info,
(struct serial_multiport_struct *) arg); (struct serial_multiport_struct *) arg);
case TIOCSERSETMULTI: case TIOCSERSETMULTI:
error = verify_area(VERIFY_READ, (void *) arg,
sizeof(struct serial_multiport_struct));
if (error)
return error;
return set_multiport_struct(info, return set_multiport_struct(info,
(struct serial_multiport_struct *) arg); (struct serial_multiport_struct *) arg);
#endif
/* /*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
* - mask passed in arg for lines of interest * - mask passed in arg for lines of interest
...@@ -2168,18 +2293,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, ...@@ -2168,18 +2293,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* RI where only 0->1 is counted. * RI where only 0->1 is counted.
*/ */
case TIOCGICOUNT: case TIOCGICOUNT:
error = verify_area(VERIFY_WRITE, (void *) arg,
sizeof(struct serial_icounter_struct));
if (error)
return error;
cli(); cli();
cnow = info->state->icount; cnow = info->state->icount;
sti(); sti();
p_cuser = (struct serial_icounter_struct *) arg; p_cuser = (struct serial_icounter_struct *) arg;
put_user(cnow.cts, &p_cuser->cts); error = put_user(cnow.cts, &p_cuser->cts);
put_user(cnow.dsr, &p_cuser->dsr); if (error) return error;
put_user(cnow.rng, &p_cuser->rng); error = put_user(cnow.dsr, &p_cuser->dsr);
put_user(cnow.dcd, &p_cuser->dcd); 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; return 0;
default: default:
...@@ -2409,7 +2534,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -2409,7 +2534,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
/* /*
* rs_hangup() --- called by tty_hangup() when a hangup is signaled. * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
*/ */
void rs_hangup(struct tty_struct *tty) static void rs_hangup(struct tty_struct *tty)
{ {
struct async_struct * info = (struct async_struct *)tty->driver_data; struct async_struct * info = (struct async_struct *)tty->driver_data;
struct serial_state *state = info->state; struct serial_state *state = info->state;
...@@ -2567,7 +2692,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, ...@@ -2567,7 +2692,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
return 0; return 0;
} }
int get_async_struct(int line, struct async_struct **ret_info) static int get_async_struct(int line, struct async_struct **ret_info)
{ {
struct async_struct *info; struct async_struct *info;
struct serial_state *sstate; struct serial_state *sstate;
...@@ -2609,7 +2734,7 @@ int get_async_struct(int line, struct async_struct **ret_info) ...@@ -2609,7 +2734,7 @@ int get_async_struct(int line, struct async_struct **ret_info)
* the IRQ chain. It also performs the serial-specific * the IRQ chain. It also performs the serial-specific
* initialization for the tty structure. * initialization for the tty structure.
*/ */
int rs_open(struct tty_struct *tty, struct file * filp) static int rs_open(struct tty_struct *tty, struct file * filp)
{ {
struct async_struct *info; struct async_struct *info;
int retval, line; int retval, line;
...@@ -2676,6 +2801,106 @@ int rs_open(struct tty_struct *tty, struct file * filp) ...@@ -2676,6 +2801,106 @@ int rs_open(struct tty_struct *tty, struct file * filp)
return 0; return 0;
} }
/*
* /proc fs routines....
*/
static int inline line_info(char *buf, struct serial_state *state)
{
struct async_struct *info = state->info, scr_info;
char stat_buf[30], control, status;
int ret;
ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
state->line, uart_config[state->type].name,
state->port, state->irq);
if (!state->port || (state->type == PORT_UNKNOWN)) {
ret += sprintf(buf+ret, "\n");
return ret;
}
/*
* 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);
return ret;
}
int rs_read_proc(char *page, char **start, off_t off, int count, 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)
break;
if (len+begin < off) {
begin += len;
len = 0;
}
}
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() and friends
...@@ -2711,9 +2936,14 @@ static void show_serial_version(void) ...@@ -2711,9 +2936,14 @@ static void show_serial_version(void)
*/ */
static int get_auto_irq(struct async_struct *info) static int get_auto_irq(struct async_struct *info)
{ {
unsigned char save_MCR, save_IER, save_ICP=0;
unsigned short ICP=0, port = info->port; unsigned char save_MCR, save_IER;
unsigned long timeout; unsigned long timeout;
#ifdef CONFIG_SERIAL_MANY_PORTS
unsigned char save_ICP=0;
unsigned short ICP=0, port = info->port;
#endif
/* /*
* Enable interrupts and see who answers * Enable interrupts and see who answers
...@@ -2722,6 +2952,7 @@ static int get_auto_irq(struct async_struct *info) ...@@ -2722,6 +2952,7 @@ static int get_auto_irq(struct async_struct *info)
cli(); cli();
save_IER = serial_inp(info, UART_IER); save_IER = serial_inp(info, UART_IER);
save_MCR = serial_inp(info, UART_MCR); save_MCR = serial_inp(info, UART_MCR);
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) { if (info->flags & ASYNC_FOURPORT) {
serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
serial_outp(info, UART_IER, 0x0f); /* enable all intrs */ serial_outp(info, UART_IER, 0x0f); /* enable all intrs */
...@@ -2729,7 +2960,9 @@ static int get_auto_irq(struct async_struct *info) ...@@ -2729,7 +2960,9 @@ static int get_auto_irq(struct async_struct *info)
save_ICP = inb_p(ICP); save_ICP = inb_p(ICP);
outb_p(0x80, ICP); outb_p(0x80, ICP);
(void) inb_p(ICP); (void) inb_p(ICP);
} else { } else
#endif
{
serial_outp(info, UART_MCR, serial_outp(info, UART_MCR,
UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
serial_outp(info, UART_IER, 0x0f); /* enable all intrs */ serial_outp(info, UART_IER, 0x0f); /* enable all intrs */
...@@ -2754,8 +2987,10 @@ static int get_auto_irq(struct async_struct *info) ...@@ -2754,8 +2987,10 @@ static int get_auto_irq(struct async_struct *info)
cli(); cli();
serial_outp(info, UART_IER, save_IER); serial_outp(info, UART_IER, save_IER);
serial_outp(info, UART_MCR, save_MCR); serial_outp(info, UART_MCR, save_MCR);
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) if (info->flags & ASYNC_FOURPORT)
outb_p(save_ICP, ICP); outb_p(save_ICP, ICP);
#endif
sti(); sti();
return(rs_irq_triggered); return(rs_irq_triggered);
} }
...@@ -2912,7 +3147,7 @@ static void autoconfig(struct serial_state * state) ...@@ -2912,7 +3147,7 @@ static void autoconfig(struct serial_state * state)
serial_outp(info, UART_LCR, 0); serial_outp(info, UART_LCR, 0);
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(info, UART_IIR) >> 5; scratch = serial_in(info, UART_IIR) >> 5;
if (scratch == 7) if (scratch == 6)
state->type = PORT_16750; state->type = PORT_16750;
} }
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
...@@ -2981,7 +3216,10 @@ int rs_init(void) ...@@ -2981,7 +3216,10 @@ int rs_init(void)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
IRQ_ports[i] = 0; IRQ_ports[i] = 0;
IRQ_timeout[i] = 0; IRQ_timeout[i] = 0;
memset(&rs_multiport[i], 0, sizeof(struct rs_multiport_struct)); #ifdef CONFIG_SERIAL_MULTIPORT
memset(&rs_multiport[i], 0,
sizeof(struct rs_multiport_struct));
#endif
} }
show_serial_version(); show_serial_version();
...@@ -2990,6 +3228,7 @@ int rs_init(void) ...@@ -2990,6 +3228,7 @@ int rs_init(void)
memset(&serial_driver, 0, sizeof(struct tty_driver)); memset(&serial_driver, 0, sizeof(struct tty_driver));
serial_driver.magic = TTY_DRIVER_MAGIC; serial_driver.magic = TTY_DRIVER_MAGIC;
serial_driver.driver_name = "serial";
serial_driver.name = "ttyS"; serial_driver.name = "ttyS";
serial_driver.major = TTY_MAJOR; serial_driver.major = TTY_MAJOR;
serial_driver.minor_start = 64; serial_driver.minor_start = 64;
...@@ -3022,6 +3261,7 @@ int rs_init(void) ...@@ -3022,6 +3261,7 @@ int rs_init(void)
serial_driver.start = rs_start; serial_driver.start = rs_start;
serial_driver.hangup = rs_hangup; serial_driver.hangup = rs_hangup;
serial_driver.wait_until_sent = rs_wait_until_sent; serial_driver.wait_until_sent = rs_wait_until_sent;
serial_driver.read_proc = rs_read_proc;
/* /*
* The callout device is just like normal device except for * The callout device is just like normal device except for
...@@ -3031,6 +3271,8 @@ int rs_init(void) ...@@ -3031,6 +3271,8 @@ int rs_init(void)
callout_driver.name = "cua"; callout_driver.name = "cua";
callout_driver.major = TTYAUX_MAJOR; callout_driver.major = TTYAUX_MAJOR;
callout_driver.subtype = SERIAL_TYPE_CALLOUT; callout_driver.subtype = SERIAL_TYPE_CALLOUT;
callout_driver.read_proc = 0;
callout_driver.proc_entry = 0;
if (tty_register_driver(&serial_driver)) if (tty_register_driver(&serial_driver))
panic("Couldn't register serial driver\n"); panic("Couldn't register serial driver\n");
...@@ -3048,22 +3290,26 @@ int rs_init(void) ...@@ -3048,22 +3290,26 @@ int rs_init(void)
state->normal_termios = serial_driver.init_termios; state->normal_termios = serial_driver.init_termios;
state->icount.cts = state->icount.dsr = state->icount.cts = state->icount.dsr =
state->icount.rng = state->icount.dcd = 0; 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;
if (state->irq == 2) if (state->irq == 2)
state->irq = 9; state->irq = 9;
if (state->type == PORT_UNKNOWN) { if (state->type == PORT_UNKNOWN) {
if (!(state->flags & ASYNC_BOOT_AUTOCONF)) if (!(state->flags & ASYNC_BOOT_AUTOCONF))
continue; continue;
if (check_region(state->port,8))
continue;
autoconfig(state); autoconfig(state);
if (state->type == PORT_UNKNOWN) if (state->type == PORT_UNKNOWN)
continue; continue;
} }
printk(KERN_INFO "tty%02d%s at 0x%04x (irq = %d) is a %s\n", printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n",
state->line, state->line,
(state->flags & ASYNC_FOURPORT) ? " FourPort" : "", (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
state->port, state->irq, state->port, state->irq,
uart_config[state->type].name); uart_config[state->type].name);
} }
return 0; return 0;
} }
...@@ -3161,5 +3407,10 @@ void cleanup_module(void) ...@@ -3161,5 +3407,10 @@ void cleanup_module(void)
if (rs_table[i].type != PORT_UNKNOWN) if (rs_table[i].type != PORT_UNKNOWN)
release_region(rs_table[i].port, 8); release_region(rs_table[i].port, 8);
} }
if (tmp_buf) {
free_page((unsigned long) tmp_buf);
tmp_buf = NULL;
}
} }
#endif /* MODULE */ #endif /* MODULE */
...@@ -63,6 +63,9 @@ ...@@ -63,6 +63,9 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/poll.h> #include <linux/poll.h>
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#endif
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -1134,6 +1137,25 @@ static void release_dev(struct file * filp) ...@@ -1134,6 +1137,25 @@ static void release_dev(struct file * filp)
if (tty->count) if (tty->count)
return; return;
/*
* Sanity check --- if tty->count is zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. But just
* in case....
*/
while (1) {
if (waitqueue_active(&tty->read_wait)) {
printk("release_dev: %s: read_wait active?!?\n",
tty_name(tty));
wake_up(&tty->read_wait);
} else if (waitqueue_active(&tty->write_wait)) {
printk("release_dev: %s: write_wait active?!?\n",
tty_name(tty));
wake_up(&tty->write_wait);
} else
break;
schedule();
}
/* /*
* We're committed; at this point, we must not block! * We're committed; at this point, we must not block!
*/ */
...@@ -1232,7 +1254,9 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1232,7 +1254,9 @@ static int tty_open(struct inode * inode, struct file * filp)
int minor; int minor;
int noctty, retval; int noctty, retval;
kdev_t device; kdev_t device;
unsigned short saved_flags;
saved_flags = filp->f_flags;
retry_open: retry_open:
noctty = filp->f_flags & O_NOCTTY; noctty = filp->f_flags & O_NOCTTY;
device = inode->i_rdev; device = inode->i_rdev;
...@@ -1240,6 +1264,7 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1240,6 +1264,7 @@ static int tty_open(struct inode * inode, struct file * filp)
if (!current->tty) if (!current->tty)
return -ENXIO; return -ENXIO;
device = current->tty->device; device = current->tty->device;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
/* noctty = 1; */ /* noctty = 1; */
} }
if (device == CONSOLE_DEV) { if (device == CONSOLE_DEV) {
...@@ -1263,6 +1288,7 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1263,6 +1288,7 @@ static int tty_open(struct inode * inode, struct file * filp)
retval = tty->driver.open(tty, filp); retval = tty->driver.open(tty, filp);
else else
retval = -ENODEV; retval = -ENODEV;
filp->f_flags = saved_flags;
if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser())
retval = -EBUSY; retval = -EBUSY;
...@@ -1830,6 +1856,10 @@ int tty_register_driver(struct tty_driver *driver) ...@@ -1830,6 +1856,10 @@ int tty_register_driver(struct tty_driver *driver)
driver->next = tty_drivers; driver->next = tty_drivers;
if (tty_drivers) tty_drivers->prev = driver; if (tty_drivers) tty_drivers->prev = driver;
tty_drivers = driver; tty_drivers = driver;
#ifdef CONFIG_PROC_FS
proc_tty_register_driver(driver);
#endif
return error; return error;
} }
...@@ -1871,6 +1901,9 @@ int tty_unregister_driver(struct tty_driver *driver) ...@@ -1871,6 +1901,9 @@ int tty_unregister_driver(struct tty_driver *driver)
if (driver->next) if (driver->next)
driver->next->prev = driver->prev; driver->next->prev = driver->prev;
#ifdef CONFIG_PROC_FS
proc_tty_unregister_driver(driver);
#endif
return 0; return 0;
} }
...@@ -1925,18 +1958,24 @@ int tty_init(void) ...@@ -1925,18 +1958,24 @@ int tty_init(void)
*/ */
memset(&dev_tty_driver, 0, sizeof(struct tty_driver)); memset(&dev_tty_driver, 0, sizeof(struct tty_driver));
dev_tty_driver.magic = TTY_DRIVER_MAGIC; dev_tty_driver.magic = TTY_DRIVER_MAGIC;
dev_tty_driver.name = "tty"; dev_tty_driver.driver_name = "/dev/tty";
dev_tty_driver.name = dev_tty_driver.driver_name + 5;
dev_tty_driver.name_base = 0; dev_tty_driver.name_base = 0;
dev_tty_driver.major = TTY_MAJOR; dev_tty_driver.major = TTY_MAJOR;
dev_tty_driver.minor_start = 0; dev_tty_driver.minor_start = 0;
dev_tty_driver.num = 1; dev_tty_driver.num = 1;
dev_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM;
dev_tty_driver.subtype = SYSTEM_TYPE_TTY;
if (tty_register_driver(&dev_tty_driver)) if (tty_register_driver(&dev_tty_driver))
panic("Couldn't register /dev/tty driver\n"); panic("Couldn't register /dev/tty driver\n");
dev_console_driver = dev_tty_driver; dev_console_driver = dev_tty_driver;
dev_console_driver.name = "console"; dev_console_driver.driver_name = "/dev/console";
dev_console_driver.name = dev_console_driver.driver_name + 5;
dev_console_driver.major = TTYAUX_MAJOR; dev_console_driver.major = TTYAUX_MAJOR;
dev_console_driver.type = TTY_DRIVER_TYPE_SYSTEM;
dev_console_driver.subtype = SYSTEM_TYPE_CONSOLE;
if (tty_register_driver(&dev_console_driver)) if (tty_register_driver(&dev_console_driver))
panic("Couldn't register /dev/console driver\n"); panic("Couldn't register /dev/console driver\n");
......
...@@ -163,10 +163,10 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt) ...@@ -163,10 +163,10 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); memcpy(&tmp_termios, tty->termios, sizeof(struct termios));
user_termio_to_kernel_termios(&tmp_termios, (struct termio *) arg); user_termio_to_kernel_termios(&tmp_termios, (struct termio *) arg);
} else { } else {
retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios)); retval = user_termios_to_kernel_termios
(&tmp_termios, (struct termios *) arg);
if (retval) if (retval)
return retval; return retval;
user_termios_to_kernel_termios(&tmp_termios, (struct termios *) arg);
} }
if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer) if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
...@@ -240,15 +240,13 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb) ...@@ -240,15 +240,13 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb)
int retval; int retval;
struct sgttyb tmp; struct sgttyb tmp;
retval = verify_area(VERIFY_WRITE, sgttyb, sizeof(struct sgttyb));
if (retval)
return retval;
tmp.sg_ispeed = 0; tmp.sg_ispeed = 0;
tmp.sg_ospeed = 0; tmp.sg_ospeed = 0;
tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_erase = tty->termios->c_cc[VERASE];
tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_kill = tty->termios->c_cc[VKILL];
tmp.sg_flags = get_sgflags(tty); tmp.sg_flags = get_sgflags(tty);
copy_to_user(sgttyb, &tmp, sizeof(tmp)); if (copy_to_user(sgttyb, &tmp, sizeof(tmp)))
return -EFAULT;
return 0; return 0;
} }
...@@ -283,14 +281,12 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb) ...@@ -283,14 +281,12 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb * sgttyb)
struct sgttyb tmp; struct sgttyb tmp;
struct termios termios; struct termios termios;
retval = verify_area(VERIFY_READ, sgttyb, sizeof(struct sgttyb));
if (retval)
return retval;
retval = tty_check_change(tty); retval = tty_check_change(tty);
if (retval) if (retval)
return retval; return retval;
termios = *tty->termios; termios = *tty->termios;
copy_from_user(&tmp, sgttyb, sizeof(tmp)); if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
return -EFAULT;
termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill; termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags); set_sgflags(&termios, tmp.sg_flags);
...@@ -305,16 +301,14 @@ static int get_tchars(struct tty_struct * tty, struct tchars * tchars) ...@@ -305,16 +301,14 @@ static int get_tchars(struct tty_struct * tty, struct tchars * tchars)
int retval; int retval;
struct tchars tmp; struct tchars tmp;
retval = verify_area(VERIFY_WRITE, tchars, sizeof(struct tchars));
if (retval)
return retval;
tmp.t_intrc = tty->termios->c_cc[VINTR]; tmp.t_intrc = tty->termios->c_cc[VINTR];
tmp.t_quitc = tty->termios->c_cc[VQUIT]; tmp.t_quitc = tty->termios->c_cc[VQUIT];
tmp.t_startc = tty->termios->c_cc[VSTART]; tmp.t_startc = tty->termios->c_cc[VSTART];
tmp.t_stopc = tty->termios->c_cc[VSTOP]; tmp.t_stopc = tty->termios->c_cc[VSTOP];
tmp.t_eofc = tty->termios->c_cc[VEOF]; tmp.t_eofc = tty->termios->c_cc[VEOF];
tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
copy_to_user(tchars, &tmp, sizeof(tmp)); if (copy_to_user(tchars, &tmp, sizeof(tmp)))
return -EFAULT;
return 0; return 0;
} }
...@@ -323,10 +317,8 @@ static int set_tchars(struct tty_struct * tty, struct tchars * tchars) ...@@ -323,10 +317,8 @@ static int set_tchars(struct tty_struct * tty, struct tchars * tchars)
int retval; int retval;
struct tchars tmp; struct tchars tmp;
retval = verify_area(VERIFY_READ, tchars, sizeof(struct tchars)); if (copy_from_user(&tmp, tchars, sizeof(tmp)))
if (retval) return -EFAULT;
return retval;
copy_from_user(&tmp, tchars, sizeof(tmp));
tty->termios->c_cc[VINTR] = tmp.t_intrc; tty->termios->c_cc[VINTR] = tmp.t_intrc;
tty->termios->c_cc[VQUIT] = tmp.t_quitc; tty->termios->c_cc[VQUIT] = tmp.t_quitc;
tty->termios->c_cc[VSTART] = tmp.t_startc; tty->termios->c_cc[VSTART] = tmp.t_startc;
...@@ -343,16 +335,14 @@ static int get_ltchars(struct tty_struct * tty, struct ltchars * ltchars) ...@@ -343,16 +335,14 @@ static int get_ltchars(struct tty_struct * tty, struct ltchars * ltchars)
int retval; int retval;
struct ltchars tmp; struct ltchars tmp;
retval = verify_area(VERIFY_WRITE, ltchars, sizeof(struct ltchars));
if (retval)
return retval;
tmp.t_suspc = tty->termios->c_cc[VSUSP]; tmp.t_suspc = tty->termios->c_cc[VSUSP];
tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */
tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; tmp.t_rprntc = tty->termios->c_cc[VREPRINT];
tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */ tmp.t_flushc = tty->termios->c_cc[VEOL2]; /* what is flushc anyway? */
tmp.t_werasc = tty->termios->c_cc[VWERASE]; tmp.t_werasc = tty->termios->c_cc[VWERASE];
tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
copy_to_user(ltchars, &tmp, sizeof(tmp)); if (copy_to_user(ltchars, &tmp, sizeof(tmp)))
return -EFAULT;
return 0; return 0;
} }
...@@ -361,10 +351,9 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars * ltchars) ...@@ -361,10 +351,9 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars * ltchars)
int retval; int retval;
struct ltchars tmp; struct ltchars tmp;
retval = verify_area(VERIFY_READ, ltchars, sizeof(struct ltchars)); if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
if (retval) return -EFAULT;
return retval;
copy_from_user(&tmp, ltchars, sizeof(tmp));
tty->termios->c_cc[VSUSP] = tmp.t_suspc; tty->termios->c_cc[VSUSP] = tmp.t_suspc;
tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */ tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; /* what is dsuspc anyway? */
tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
...@@ -427,13 +416,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, ...@@ -427,13 +416,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
return set_ltchars(real_tty, (struct ltchars *) arg); return set_ltchars(real_tty, (struct ltchars *) arg);
#endif #endif
case TCGETS: case TCGETS:
retval = verify_area(VERIFY_WRITE, (void *) arg, return kernel_termios_to_user_termios
sizeof (struct termios)); ((struct termios *)arg,
if (retval)
return retval;
kernel_termios_to_user_termios((struct termios *)arg,
real_tty->termios); real_tty->termios);
return 0;
case TCSETSF: case TCSETSF:
opt |= TERMIOS_FLUSH; opt |= TERMIOS_FLUSH;
case TCSETSW: case TCSETSW:
...@@ -499,53 +484,31 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, ...@@ -499,53 +484,31 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
} }
return 0; return 0;
case TIOCOUTQ: case TIOCOUTQ:
retval = verify_area(VERIFY_WRITE, (void *) arg, return put_user(tty->driver.chars_in_buffer ?
sizeof (int)); tty->driver.chars_in_buffer(tty) : 0,
if (retval)
return retval;
if (tty->driver.chars_in_buffer)
put_user(tty->driver.chars_in_buffer(tty),
(int *) arg); (int *) arg);
else
put_user(0, (int *) arg);
return 0;
case TIOCINQ: case TIOCINQ:
retval = verify_area(VERIFY_WRITE, (void *) arg,
sizeof (unsigned int));
if (retval)
return retval;
retval = tty->read_cnt; retval = tty->read_cnt;
if (L_ICANON(tty)) if (L_ICANON(tty))
retval = inq_canon(tty); retval = inq_canon(tty);
put_user(retval, (unsigned int *) arg); return put_user(retval, (unsigned int *) arg);
return 0;
case TIOCGLCKTRMIOS: case TIOCGLCKTRMIOS:
retval = verify_area(VERIFY_WRITE, (void *) arg, return kernel_termios_to_user_termios
sizeof (struct termios)); ((struct termios *)arg,
if (retval)
return retval;
kernel_termios_to_user_termios((struct termios *)arg,
real_tty->termios_locked); real_tty->termios_locked);
return 0;
case TIOCSLCKTRMIOS: case TIOCSLCKTRMIOS:
if (!suser()) if (!suser())
return -EPERM; return -EPERM;
retval = verify_area(VERIFY_READ, (void *) arg, return user_termios_to_kernel_termios
sizeof (struct termios)); (real_tty->termios_locked,
if (retval)
return retval;
user_termios_to_kernel_termios(real_tty->termios_locked,
(struct termios *) arg); (struct termios *) arg);
return 0;
case TIOCPKT: case TIOCPKT:
if (tty->driver.type != TTY_DRIVER_TYPE_PTY || if (tty->driver.type != TTY_DRIVER_TYPE_PTY ||
tty->driver.subtype != PTY_TYPE_MASTER) tty->driver.subtype != PTY_TYPE_MASTER)
return -ENOTTY; return -ENOTTY;
retval = verify_area(VERIFY_READ, (void *) arg, retval = get_user(retval, (int *) arg);
sizeof (int));
if (retval) if (retval)
return retval; return retval;
get_user(retval, (int *) arg);
if (retval) { if (retval) {
if (!tty->packet) { if (!tty->packet) {
tty->packet = 1; tty->packet = 1;
......
...@@ -358,6 +358,7 @@ ppp_first_time (void) ...@@ -358,6 +358,7 @@ ppp_first_time (void)
*/ */
(void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc));
ppp_ldisc.magic = TTY_LDISC_MAGIC; ppp_ldisc.magic = TTY_LDISC_MAGIC;
ppp_ldisc.name = "ppp";
ppp_ldisc.open = ppp_tty_open; ppp_ldisc.open = ppp_tty_open;
ppp_ldisc.close = ppp_tty_close; ppp_ldisc.close = ppp_tty_close;
ppp_ldisc.read = ppp_tty_read; ppp_ldisc.read = ppp_tty_read;
......
...@@ -1120,6 +1120,7 @@ int slip_init_ctrl_dev(struct device *dummy) ...@@ -1120,6 +1120,7 @@ int slip_init_ctrl_dev(struct device *dummy)
/* Fill in our line protocol discipline, and register it */ /* Fill in our line protocol discipline, and register it */
memset(&sl_ldisc, 0, sizeof(sl_ldisc)); memset(&sl_ldisc, 0, sizeof(sl_ldisc));
sl_ldisc.magic = TTY_LDISC_MAGIC; sl_ldisc.magic = TTY_LDISC_MAGIC;
sl_ldisc.name = "slip";
sl_ldisc.flags = 0; sl_ldisc.flags = 0;
sl_ldisc.open = slip_open; sl_ldisc.open = slip_open;
sl_ldisc.close = slip_close; sl_ldisc.close = slip_close;
......
...@@ -917,12 +917,29 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) ...@@ -917,12 +917,29 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
pcibios_write_config_word(bus->number, devfn, pcibios_write_config_word(bus->number, devfn,
PCI_STATUS, 0xffff); PCI_STATUS, 0xffff);
/* /*
* Configure the bus numbers for this bridge: * Read the existing primary/secondary/subordinate bus
* number configuration to determine if the PCI bridge
* has already been configured by the system. If so,
* do not modify the configuration, merely note it.
*/ */
pcibios_read_config_dword(bus->number, devfn, 0x18, pcibios_read_config_dword(bus->number, devfn, 0x18,
&buses); &buses);
if ((buses & 0xFFFFFF) != 0)
{
child->primary = buses & 0xFF;
child->secondary = (buses >> 8) & 0xFF;
child->subordinate = (buses >> 16) & 0xFF;
child->number = child->secondary;
max = scan_bus(child, mem_startp);
}
else
{
/*
* Configure the bus numbers for this bridge:
*/
buses &= 0xff000000; buses &= 0xff000000;
buses |= (((unsigned int)(child->primary) << 0) | buses |=
(((unsigned int)(child->primary) << 0) |
((unsigned int)(child->secondary) << 8) | ((unsigned int)(child->secondary) << 8) |
((unsigned int)(child->subordinate) << 16)); ((unsigned int)(child->subordinate) << 16));
pcibios_write_config_dword(bus->number, devfn, 0x18, pcibios_write_config_dword(bus->number, devfn, 0x18,
...@@ -940,6 +957,7 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp) ...@@ -940,6 +957,7 @@ static unsigned int scan_bus(struct pci_bus *bus, unsigned long *mem_startp)
| ((unsigned int)(child->subordinate) << 16); | ((unsigned int)(child->subordinate) << 16);
pcibios_write_config_dword(bus->number, devfn, 0x18, pcibios_write_config_dword(bus->number, devfn, 0x18,
buses); buses);
}
pcibios_write_config_word(bus->number, devfn, pcibios_write_config_word(bus->number, devfn,
PCI_COMMAND, cr); PCI_COMMAND, cr);
} }
......
...@@ -684,6 +684,7 @@ AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id); ...@@ -684,6 +684,7 @@ AM53C974_write_8(CNTLREG1, CNTLREG1_DISR | instance->this_id);
AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */ AM53C974_write_8(CMDREG, CMDREG_RBUS); /* reset SCSI bus */
udelay(10); udelay(10);
AM53C974_config_after_reset(instance); AM53C974_config_after_reset(instance);
udelay(500000);
return(1); return(1);
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* /*
Linux Driver for BusLogic MultiMaster SCSI Host Adapters Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com> Copyright 1995 by Leonard N. Zubkoff <lnz@dandelion.com>
...@@ -17,9 +17,12 @@ ...@@ -17,9 +17,12 @@
The author respectfully requests that any modifications to this software be The author respectfully requests that any modifications to this software be
sent directly to him for evaluation and testing. sent directly to him for evaluation and testing.
Special thanks to Wayne Yen and Alex Win of BusLogic, whose advice has been Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
invaluable, to David Gentzel, for writing the original Linux BusLogic driver, advice has been invaluable, to David Gentzel, for writing the original Linux
and to Paul Gortmaker, for being such a dedicated test site. BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
Manager available as freely redistributable source code.
*/ */
...@@ -29,6 +32,8 @@ ...@@ -29,6 +32,8 @@
of the Linux Kernel and SCSI Subsystem. of the Linux Kernel and SCSI Subsystem.
*/ */
typedef kdev_t KernelDevice_T;
typedef struct proc_dir_entry PROC_DirectoryEntry_T;
typedef struct pt_regs Registers_T; typedef struct pt_regs Registers_T;
typedef Scsi_Host_Template SCSI_Host_Template_T; typedef Scsi_Host_Template SCSI_Host_Template_T;
typedef struct Scsi_Host SCSI_Host_T; typedef struct Scsi_Host SCSI_Host_T;
...@@ -36,21 +41,22 @@ typedef struct scsi_device SCSI_Device_T; ...@@ -36,21 +41,22 @@ typedef struct scsi_device SCSI_Device_T;
typedef struct scsi_disk SCSI_Disk_T; typedef struct scsi_disk SCSI_Disk_T;
typedef struct scsi_cmnd SCSI_Command_T; typedef struct scsi_cmnd SCSI_Command_T;
typedef struct scatterlist SCSI_ScatterList_T; typedef struct scatterlist SCSI_ScatterList_T;
typedef kdev_t KernelDevice_T;
/* /*
Define prototypes for the BusLogic Driver Interface Functions. Define prototypes for the BusLogic Driver Interface Functions.
*/ */
const char *BusLogic_DriverInfo(SCSI_Host_T *); extern PROC_DirectoryEntry_T BusLogic_ProcDirectoryEntry;
int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *); extern const char *BusLogic_DriverInfo(SCSI_Host_T *);
int BusLogic_ReleaseHostAdapter(SCSI_Host_T *); extern int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *);
int BusLogic_QueueCommand(SCSI_Command_T *, extern int BusLogic_ReleaseHostAdapter(SCSI_Host_T *);
extern int BusLogic_QueueCommand(SCSI_Command_T *,
void (*CompletionRoutine)(SCSI_Command_T *)); void (*CompletionRoutine)(SCSI_Command_T *));
int BusLogic_AbortCommand(SCSI_Command_T *); extern int BusLogic_AbortCommand(SCSI_Command_T *);
int BusLogic_ResetCommand(SCSI_Command_T *, unsigned int); extern int BusLogic_ResetCommand(SCSI_Command_T *, unsigned int);
int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); extern int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int);
/* /*
...@@ -60,8 +66,8 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -60,8 +66,8 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
#define BUSLOGIC \ #define BUSLOGIC \
{ NULL, /* Next */ \ { NULL, /* Next */ \
NULL, /* Usage Count Pointer */ \ NULL, /* Usage Count Pointer */ \
NULL, /* /proc Directory Entry */ \ &BusLogic_ProcDirectoryEntry, /* /proc Directory Entry */ \
NULL, /* /proc Info Function */ \ BusLogic_ProcDirectoryInfo, /* /proc Info Function */ \
"BusLogic", /* Driver Name */ \ "BusLogic", /* Driver Name */ \
BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \ BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \
BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \ BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \
...@@ -71,7 +77,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -71,7 +77,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
BusLogic_AbortCommand, /* Abort Command Function */ \ BusLogic_AbortCommand, /* Abort Command Function */ \
BusLogic_ResetCommand, /* Reset Command Function */ \ BusLogic_ResetCommand, /* Reset Command Function */ \
NULL, /* Slave Attach Function */ \ NULL, /* Slave Attach Function */ \
BusLogic_BIOSDiskParameters, /* Disk BIOS Parameters */ \ BusLogic_BIOSDiskParameters, /* BIOS Disk Parameters */ \
0, /* Can Queue */ \ 0, /* Can Queue */ \
0, /* This ID */ \ 0, /* This ID */ \
0, /* Scatter/Gather Table Size */ \ 0, /* Scatter/Gather Table Size */ \
...@@ -89,17 +95,10 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -89,17 +95,10 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
/* /*
Define the maximum number of BusLogic Host Adapters that are supported. Define the maximum number of BusLogic Host Adapters supported by this driver.
*/
#define BusLogic_MaxHostAdapters 10
/*
Define the maximum number of I/O Addresses that may be probed.
*/ */
#define BusLogic_IO_MaxProbeAddresses 16 #define BusLogic_MaxHostAdapters 16
/* /*
...@@ -112,7 +111,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -112,7 +111,7 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
/* /*
Define the maximum number of Scatter/Gather Segments used by this driver. Define the maximum number of Scatter/Gather Segments used by this driver.
For optimal performance, it is important that this limit be at least as For optimal performance, it is important that this limit be at least as
large as the maximum single request generated by the I/O Subsystem. large as the largest single request generated by the I/O Subsystem.
*/ */
#define BusLogic_ScatterGatherLimit 128 #define BusLogic_ScatterGatherLimit 128
...@@ -126,7 +125,8 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -126,7 +125,8 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
#define BusLogic_MaxTaggedQueueDepth 63 #define BusLogic_MaxTaggedQueueDepth 63
#define BusLogic_PreferredTaggedQueueDepth 28 #define BusLogic_PreferredTaggedQueueDepth 28
#define BusLogic_TaggedQueueDepth_BB 2 #define BusLogic_TaggedQueueDepthBounceBuffers 2
#define BusLogic_TaggedQueueDepthAutomatic 0
#define BusLogic_UntaggedQueueDepth 3 #define BusLogic_UntaggedQueueDepth 3
...@@ -141,122 +141,334 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *); ...@@ -141,122 +141,334 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
/* /*
Define the possible Probe Options. Define the Host Adapter Line and Message Buffer Sizes.
*/ */
#define BusLogic_NoProbe 1 #define BusLogic_LineBufferSize 100
#define BusLogic_NoProbeISA 2 #define BusLogic_MessageBufferSize 8900
#define BusLogic_NoSortPCI 4
/* /*
Define the possible Local Options. Define the Driver Message Levels.
*/ */
#define BusLogic_InhibitTargetInquiry 1 typedef enum BusLogic_MessageLevel
{
BusLogic_AnnounceLevel = 0,
BusLogic_InfoLevel = 1,
BusLogic_NoticeLevel = 2,
BusLogic_WarningLevel = 3,
BusLogic_ErrorLevel = 4
}
BusLogic_MessageLevel_T;
static char
*BusLogic_MessageLevelMap[] =
{ KERN_INFO, KERN_INFO, KERN_NOTICE, KERN_WARNING, KERN_ERR };
/* /*
Define the possible Global Options. Define the types of BusLogic Host Adapters that are supported and the number
of I/O Addresses required by each type.
*/ */
#define BusLogic_TraceProbe 1 typedef enum
#define BusLogic_TraceHardReset 2 {
#define BusLogic_TraceConfiguration 4 BusLogic_MultiMaster = 1,
#define BusLogic_TraceErrors 8 BusLogic_FlashPoint = 2
#define BusLogic_TraceQueueDepths 16 }
__attribute__ ((packed))
BusLogic_HostAdapterType_T;
#define BusLogic_MultiMasterAddressCount 4
#define BusLogic_FlashPointAddressCount 256
static int
BusLogic_HostAdapter_AddressCount[3] =
{ 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
/* /*
Define the possible Error Recovery Strategy Options. Define the possible Host Adapter Bus Types.
*/ */
#define BusLogic_ErrorRecovery_Default 0 typedef enum
#define BusLogic_ErrorRecovery_HardReset 1 {
#define BusLogic_ErrorRecovery_BusDeviceReset 2 BusLogic_Unknown_Bus = 0,
#define BusLogic_ErrorRecovery_None 3 BusLogic_ISA_Bus = 1,
BusLogic_EISA_Bus = 2,
BusLogic_PCI_Bus = 3,
BusLogic_VESA_Bus = 4,
BusLogic_MCA_Bus = 5
}
BusLogic_HostAdapterBusType_T;
static char static char
*BusLogic_ErrorRecoveryStrategyNames[] = *BusLogic_HostAdapterBusNames[] =
{ "Default", "Hard Reset", "Bus Device Reset", "None" }, { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
*BusLogic_ErrorRecoveryStrategyLetters[] =
{ "D", "H", "B", "N" }; static BusLogic_HostAdapterBusType_T
BusLogic_HostAdapterBusTypes[] =
{ BusLogic_VESA_Bus, /* BT-4xx */
BusLogic_ISA_Bus, /* BT-5xx */
BusLogic_MCA_Bus, /* BT-6xx */
BusLogic_EISA_Bus, /* BT-7xx */
BusLogic_Unknown_Bus, /* BT-8xx */
BusLogic_PCI_Bus }; /* BT-9xx */
/*
Define the possible Host Adapter BIOS Disk Geometry Translations.
*/
typedef enum BusLogic_BIOS_DiskGeometryTranslation
{
BusLogic_BIOS_Disk_Not_Installed = 0,
BusLogic_BIOS_Disk_Installed_64x32 = 1,
BusLogic_BIOS_Disk_Installed_128x32 = 2,
BusLogic_BIOS_Disk_Installed_255x63 = 3
}
__attribute__ ((packed))
BusLogic_BIOS_DiskGeometryTranslation_T;
/*
Define a Boolean data type.
*/
typedef enum { false, true } __attribute__ ((packed)) boolean;
/*
Define a 32 bit I/O Address data type.
*/
typedef unsigned int BusLogic_IO_Address_T;
/*
Define a 32 bit PCI Bus Address data type.
*/
typedef unsigned int BusLogic_PCI_Address_T;
/* /*
Define a boolean data type. Define a 32 bit Bus Address data type.
*/ */
#define false 0 typedef unsigned int BusLogic_BusAddress_T;
#define true 1
typedef unsigned char boolean;
/* /*
Define a 32 bit bus address data type. Define a 32 bit Byte Count data type.
*/ */
typedef unsigned int bus_address_t; typedef unsigned int BusLogic_ByteCount_T;
/*
Define a 10^18 Statistics Byte Counter data type.
*/
typedef struct BusLogic_ByteCounter
{
unsigned int Units;
unsigned int Billions;
}
BusLogic_ByteCounter_T;
/*
Define the structure for I/O Address and Bus Probing Information.
*/
typedef struct BusLogic_ProbeInfo
{
BusLogic_IO_Address_T IO_Address;
BusLogic_PCI_Address_T PCI_Address;
BusLogic_HostAdapterType_T HostAdapterType:2;
BusLogic_HostAdapterBusType_T HostAdapterBusType:3;
unsigned char :3;
unsigned char Bus;
unsigned char Device;
unsigned char IRQ_Channel;
}
BusLogic_ProbeInfo_T;
/*
BusLogic_ISA_StandardAddresses is the list of standard ISA I/O Addresses at
which BusLogic MultiMaster Host Adapters may potentially be found. The first
I/O Address 0x330 is known as the "Primary" I/O Address. A Host Adapter
configured to use the Primary I/O Address will always be the preferred boot
device.
*/
#define BusLogic_ISA_StandardAddressesCount 6
static BusLogic_IO_Address_T
BusLogic_ISA_StandardAddresses[BusLogic_ISA_StandardAddressesCount] =
{ 0x330, 0x334, 0x230, 0x234, 0x130, 0x134 };
/*
Define the Probe Options.
*/
typedef union BusLogic_ProbeOptions
{
unsigned short All;
struct {
boolean NoProbe:1; /* Bit 0 */
boolean NoProbeISA:1; /* Bit 1 */
boolean NoProbePCI:1; /* Bit 2 */
boolean NoSortPCI:1; /* Bit 3 */
boolean ProbeMultiMasterFirst:1; /* Bit 4 */
boolean ProbeFlashPointFirst:1; /* Bit 5 */
} Bits;
}
BusLogic_ProbeOptions_T;
/*
Define the Global Options.
*/
typedef union BusLogic_GlobalOptions
{
unsigned short All;
struct {
boolean TraceProbe:1; /* Bit 0 */
boolean TraceHardReset:1; /* Bit 1 */
boolean TraceConfiguration:1; /* Bit 2 */
boolean TraceErrors:1; /* Bit 3 */
} Bits;
}
BusLogic_GlobalOptions_T;
/*
Define the Local Options.
*/
typedef union BusLogic_LocalOptions
{
unsigned short All;
struct {
boolean InhibitTargetInquiry:1; /* Bit 0 */
boolean InhibitInterruptTest:1; /* Bit 1 */
} Bits;
}
BusLogic_LocalOptions_T;
/*
Define the Error Recovery Strategy Options.
*/
typedef enum
{
BusLogic_ErrorRecovery_Default = 0,
BusLogic_ErrorRecovery_BusDeviceReset = 1,
BusLogic_ErrorRecovery_HardReset = 2,
BusLogic_ErrorRecovery_None = 3
}
__attribute__ ((packed))
BusLogic_ErrorRecoveryStrategy_T;
static char
*BusLogic_ErrorRecoveryStrategyNames[] =
{ "Default", "Bus Device Reset", "Hard Reset", "None" },
BusLogic_ErrorRecoveryStrategyLetters[] =
{ 'D', 'B', 'H', 'N' };
/* /*
Define the BusLogic SCSI Host Adapter I/O Register Offsets. Define the BusLogic SCSI Host Adapter I/O Register Offsets.
*/ */
#define BusLogic_IO_PortCount 4 /* I/O Registers */ #define BusLogic_ControlRegisterOffset 0 /* WO register */
#define BusLogic_ControlRegister 0 /* WO register */ #define BusLogic_StatusRegisterOffset 0 /* RO register */
#define BusLogic_StatusRegister 0 /* RO register */ #define BusLogic_CommandParameterRegisterOffset 1 /* WO register */
#define BusLogic_CommandParameterRegister 1 /* WO register */ #define BusLogic_DataInRegisterOffset 1 /* RO register */
#define BusLogic_DataInRegister 1 /* RO register */ #define BusLogic_InterruptRegisterOffset 2 /* RO register */
#define BusLogic_InterruptRegister 2 /* RO register */ #define BusLogic_GeometryRegisterOffset 3 /* RO register */
#define BusLogic_GeometryRegister 3 /* RO register */
/* /*
Define the bits in the write-only Control Register. Define the structure of the write-only Control Register.
*/ */
#define BusLogic_ReservedCR 0x0F typedef union BusLogic_ControlRegister
#define BusLogic_SCSIBusReset 0x10 {
#define BusLogic_InterruptReset 0x20 unsigned char All;
#define BusLogic_SoftReset 0x40 struct {
#define BusLogic_HardReset 0x80 unsigned char :4; /* Bits 0-3 */
boolean SCSIBusReset:1; /* Bit 4 */
boolean InterruptReset:1; /* Bit 5 */
boolean SoftReset:1; /* Bit 6 */
boolean HardReset:1; /* Bit 7 */
} Bits;
}
BusLogic_ControlRegister_T;
/* /*
Define the bits in the read-only Status Register. Define the structure of the read-only Status Register.
*/ */
#define BusLogic_CommandInvalid 0x01 typedef union BusLogic_StatusRegister
#define BusLogic_ReservedSR 0x02 {
#define BusLogic_DataInRegisterReady 0x04 unsigned char All;
#define BusLogic_CommandParameterRegisterBusy 0x08 struct {
#define BusLogic_HostAdapterReady 0x10 boolean CommandInvalid:1; /* Bit 0 */
#define BusLogic_InitializationRequired 0x20 boolean Reserved:1; /* Bit 1 */
#define BusLogic_DiagnosticFailure 0x40 boolean DataInRegisterReady:1; /* Bit 2 */
#define BusLogic_DiagnosticActive 0x80 boolean CommandParameterRegisterBusy:1; /* Bit 3 */
boolean HostAdapterReady:1; /* Bit 4 */
boolean InitializationRequired:1; /* Bit 5 */
boolean DiagnosticFailure:1; /* Bit 6 */
boolean DiagnosticActive:1; /* Bit 7 */
} Bits;
}
BusLogic_StatusRegister_T;
/* /*
Define the bits in the read-only Interrupt Register. Define the structure of the read-only Interrupt Register.
*/ */
#define BusLogic_IncomingMailboxLoaded 0x01 typedef union BusLogic_InterruptRegister
#define BusLogic_OutgoingMailboxAvailable 0x02 {
#define BusLogic_CommandComplete 0x04 unsigned char All;
#define BusLogic_SCSIResetState 0x08 struct {
#define BusLogic_ReservedIR 0x70 boolean IncomingMailboxLoaded:1; /* Bit 0 */
#define BusLogic_InterruptValid 0x80 boolean OutgoingMailboxAvailable:1; /* Bit 1 */
boolean CommandComplete:1; /* Bit 2 */
boolean ExternalBusReset:1; /* Bit 3 */
unsigned char Reserved:3; /* Bits 4-6 */
boolean InterruptValid:1; /* Bit 7 */
} Bits;
}
BusLogic_InterruptRegister_T;
/* /*
Define the bits in the read-only Geometry Register. Define the structure of the read-only Geometry Register.
*/ */
#define BusLogic_Drive0Geometry 0x03 typedef union BusLogic_GeometryRegister
#define BusLogic_Drive1Geometry 0x0C {
#define BusLogic_ReservedGR 0x70 unsigned char All;
#define BusLogic_ExtendedTranslationEnabled 0x80 struct {
BusLogic_BIOS_DiskGeometryTranslation_T Drive0Geometry:2; /* Bits 0-1 */
BusLogic_BIOS_DiskGeometryTranslation_T Drive1Geometry:2; /* Bits 2-3 */
unsigned char :3; /* Bits 4-6 */
boolean ExtendedTranslationEnabled:1; /* Bit 7 */
} Bits;
}
BusLogic_GeometryRegister_T;
/* /*
...@@ -293,8 +505,8 @@ typedef enum ...@@ -293,8 +505,8 @@ typedef enum
BusLogic_ExecuteSCSICommand = 0x83, BusLogic_ExecuteSCSICommand = 0x83,
BusLogic_InquireFirmwareVersion3rdDigit = 0x84, BusLogic_InquireFirmwareVersion3rdDigit = 0x84,
BusLogic_InquireFirmwareVersionLetter = 0x85, BusLogic_InquireFirmwareVersionLetter = 0x85,
BusLogic_InquireGenericIOPortInformation = 0x86, BusLogic_InquirePCIHostAdapterInformation = 0x86,
BusLogic_InquireControllerModelNumber = 0x8B, BusLogic_InquireHostAdapterModelNumber = 0x8B,
BusLogic_InquireSynchronousPeriod = 0x8C, BusLogic_InquireSynchronousPeriod = 0x8C,
BusLogic_InquireExtendedSetupInformation = 0x8D, BusLogic_InquireExtendedSetupInformation = 0x8D,
BusLogic_EnableStrictRoundRobinMode = 0x8F, BusLogic_EnableStrictRoundRobinMode = 0x8F,
...@@ -341,7 +553,7 @@ typedef unsigned char BusLogic_InstalledDevices8_T[8]; ...@@ -341,7 +553,7 @@ typedef unsigned char BusLogic_InstalledDevices8_T[8];
Define the Inquire Target Devices reply type. Inquire Target Devices only Define the Inquire Target Devices reply type. Inquire Target Devices only
tests Logical Unit 0 of each Target Device unlike the Inquire Installed tests Logical Unit 0 of each Target Device unlike the Inquire Installed
Devices commands which test Logical Units 0 - 7. Two bytes are returned, Devices commands which test Logical Units 0 - 7. Two bytes are returned,
where bit 0 set indicates that Target Device 0 exists, and so on. where byte 0 bit 0 set indicates that Target Device 0 exists, and so on.
*/ */
typedef unsigned short BusLogic_InstalledDevices_T; typedef unsigned short BusLogic_InstalledDevices_T;
...@@ -392,7 +604,7 @@ typedef BusLogic_SynchronousValue_T ...@@ -392,7 +604,7 @@ typedef BusLogic_SynchronousValue_T
typedef struct BusLogic_SetupInformation typedef struct BusLogic_SetupInformation
{ {
boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */ boolean SynchronousInitiationEnabled:1; /* Byte 0 Bit 0 */
boolean ParityCheckEnabled:1; /* Byte 0 Bit 1 */ boolean ParityCheckingEnabled:1; /* Byte 0 Bit 1 */
unsigned char :6; /* Byte 0 Bits 2-7 */ unsigned char :6; /* Byte 0 Bits 2-7 */
unsigned char BusTransferRate; /* Byte 1 */ unsigned char BusTransferRate; /* Byte 1 */
unsigned char PreemptTimeOnBus; /* Byte 2 */ unsigned char PreemptTimeOnBus; /* Byte 2 */
...@@ -419,8 +631,9 @@ BusLogic_SetupInformation_T; ...@@ -419,8 +631,9 @@ BusLogic_SetupInformation_T;
typedef struct BusLogic_ExtendedMailboxRequest typedef struct BusLogic_ExtendedMailboxRequest
{ {
unsigned char MailboxCount; /* Byte 0 */ unsigned char MailboxCount; /* Byte 0 */
bus_address_t BaseMailboxAddress __attribute__ ((packed)); /* Bytes 1-4 */ BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 1-4 */
} }
__attribute__ ((packed))
BusLogic_ExtendedMailboxRequest_T; BusLogic_ExtendedMailboxRequest_T;
...@@ -439,12 +652,28 @@ typedef unsigned char BusLogic_FirmwareVersionLetter_T; ...@@ -439,12 +652,28 @@ typedef unsigned char BusLogic_FirmwareVersionLetter_T;
/* /*
Define the Inquire Generic I/O Port Information reply type. Define the Inquire PCI Host Adapter Information reply type. The ISA
Compatible I/O Port values are defined here and are also used with
the Modify I/O Address command.
*/ */
typedef struct BusLogic_GenericIOPortInformation typedef enum BusLogic_ISACompatibleIOPort
{ {
unsigned char ISACompatibleIOPort; /* Byte 0 */ BusLogic_IO_330 = 0,
BusLogic_IO_334 = 1,
BusLogic_IO_230 = 2,
BusLogic_IO_234 = 3,
BusLogic_IO_130 = 4,
BusLogic_IO_134 = 5,
BusLogic_IO_Disable = 6,
BusLogic_IO_Disable2 = 7
}
__attribute__ ((packed))
BusLogic_ISACompatibleIOPort_T;
typedef struct BusLogic_PCIHostAdapterInformation
{
BusLogic_ISACompatibleIOPort_T ISACompatibleIOPort; /* Byte 0 */
unsigned char PCIAssignedIRQChannel; /* Byte 1 */ unsigned char PCIAssignedIRQChannel; /* Byte 1 */
boolean LowByteTerminated:1; /* Byte 2 Bit 0 */ boolean LowByteTerminated:1; /* Byte 2 Bit 0 */
boolean HighByteTerminated:1; /* Byte 2 Bit 1 */ boolean HighByteTerminated:1; /* Byte 2 Bit 1 */
...@@ -452,17 +681,17 @@ typedef struct BusLogic_GenericIOPortInformation ...@@ -452,17 +681,17 @@ typedef struct BusLogic_GenericIOPortInformation
boolean JP1:1; /* Byte 2 Bit 4 */ boolean JP1:1; /* Byte 2 Bit 4 */
boolean JP2:1; /* Byte 2 Bit 5 */ boolean JP2:1; /* Byte 2 Bit 5 */
boolean JP3:1; /* Byte 2 Bit 6 */ boolean JP3:1; /* Byte 2 Bit 6 */
boolean Valid:1; /* Byte 2 Bit 7 */ boolean GenericInfoValid:1; /* Byte 2 Bit 7 */
unsigned char :8; /* Byte 3 */ unsigned char :8; /* Byte 3 */
} }
BusLogic_GenericIOPortInformation_T; BusLogic_PCIHostAdapterInformation_T;
/* /*
Define the Inquire Controller Model Number reply type. Define the Inquire Host Adapter Model Number reply type.
*/ */
typedef unsigned char BusLogic_ControllerModelNumber_T[5]; typedef unsigned char BusLogic_HostAdapterModelNumber_T[5];
/* /*
...@@ -484,18 +713,21 @@ typedef struct BusLogic_ExtendedSetupInformation ...@@ -484,18 +713,21 @@ typedef struct BusLogic_ExtendedSetupInformation
unsigned char BIOS_Address; /* Byte 1 */ unsigned char BIOS_Address; /* Byte 1 */
unsigned short ScatterGatherLimit; /* Bytes 2-3 */ unsigned short ScatterGatherLimit; /* Bytes 2-3 */
unsigned char MailboxCount; /* Byte 4 */ unsigned char MailboxCount; /* Byte 4 */
bus_address_t BaseMailboxAddress __attribute__ ((packed)); /* Bytes 5-8 */ BusLogic_BusAddress_T BaseMailboxAddress; /* Bytes 5-8 */
struct { unsigned char :6; /* Byte 9 Bits 0-5 */ struct { unsigned char :2; /* Byte 9 Bits 0-1 */
boolean LevelSensitiveInterrupts:1; /* Byte 9 Bit 6 */ boolean FastOnEISA:1; /* Byte 9 Bit 2 */
unsigned char :3; /* Byte 9 Bits 3-5 */
boolean LevelSensitiveInterrupt:1; /* Byte 9 Bit 6 */
unsigned char :1; } Misc; /* Byte 9 Bit 7 */ unsigned char :1; } Misc; /* Byte 9 Bit 7 */
unsigned char FirmwareRevision[3]; /* Bytes 10-12 */ unsigned char FirmwareRevision[3]; /* Bytes 10-12 */
boolean HostWideSCSI:1; /* Byte 13 Bit 0 */ boolean HostWideSCSI:1; /* Byte 13 Bit 0 */
boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */ boolean HostDifferentialSCSI:1; /* Byte 13 Bit 1 */
boolean HostAutomaticConfiguration:1; /* Byte 13 Bit 2 */ boolean HostSupportsSCAM:1; /* Byte 13 Bit 2 */
boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */ boolean HostUltraSCSI:1; /* Byte 13 Bit 3 */
boolean HostSmartTermination:1; /* Byte 13 Bit 4 */ boolean HostSmartTermination:1; /* Byte 13 Bit 4 */
unsigned char :3; /* Byte 13 Bits 5-7 */ unsigned char :3; /* Byte 13 Bits 5-7 */
} }
__attribute__ ((packed))
BusLogic_ExtendedSetupInformation_T; BusLogic_ExtendedSetupInformation_T;
...@@ -503,10 +735,13 @@ BusLogic_ExtendedSetupInformation_T; ...@@ -503,10 +735,13 @@ BusLogic_ExtendedSetupInformation_T;
Define the Enable Strict Round Robin Mode request type. Define the Enable Strict Round Robin Mode request type.
*/ */
#define BusLogic_AggressiveRoundRobinMode 0x00 typedef enum BusLogic_RoundRobinModeRequest
#define BusLogic_StrictRoundRobinMode 0x01 {
BusLogic_AggressiveRoundRobinMode = 0,
typedef unsigned char BusLogic_RoundRobinModeRequest_T; BusLogic_StrictRoundRobinMode = 1
}
__attribute__ ((packed))
BusLogic_RoundRobinModeRequest_T;
/* /*
...@@ -525,21 +760,86 @@ BusLogic_FetchHostAdapterLocalRAMRequest_T; ...@@ -525,21 +760,86 @@ BusLogic_FetchHostAdapterLocalRAMRequest_T;
/* /*
Define the Host Adapter Local RAM Auto SCSI Byte 15 reply structure. Define the Host Adapter Local RAM AutoSCSI structure.
*/ */
typedef struct BusLogic_AutoSCSIByte15 typedef struct BusLogic_AutoSCSIData
{ {
unsigned char LowByteTerminated:1; /* Bit 0 */ unsigned char InternalFactorySignature[2]; /* Bytes 0-1 */
unsigned char :1; /* Bit 1 */ unsigned char InformationByteCount; /* Byte 2 */
unsigned char HighByteTerminated:1; /* Bit 2 */ unsigned char HostAdapterType[6]; /* Bytes 3-8 */
unsigned char :5; /* Bits 3-7 */ unsigned char :8; /* Byte 9 */
boolean FloppyEnabled:1; /* Byte 10 Bit 0 */
boolean FloppySecondary:1; /* Byte 10 Bit 1 */
boolean LevelSensitiveInterrupt:1; /* Byte 10 Bit 2 */
unsigned char :2; /* Byte 10 Bits 3-4 */
unsigned char SystemRAMAreaForBIOS:3; /* Byte 10 Bits 5-7 */
unsigned char DMA_Channel:7; /* Byte 11 Bits 0-6 */
boolean DMA_AutoConfiguration:1; /* Byte 11 Bit 7 */
unsigned char IRQ_Channel:7; /* Byte 12 Bits 0-6 */
boolean IRQ_AutoConfiguration:1; /* Byte 12 Bit 7 */
unsigned char DMA_TransferRate; /* Byte 13 */
unsigned char SCSI_ID; /* Byte 14 */
boolean LowByteTerminated:1; /* Byte 15 Bit 0 */
boolean ParityCheckingEnabled:1; /* Byte 15 Bit 1 */
boolean HighByteTerminated:1; /* Byte 15 Bit 2 */
boolean NoisyCablingEnvironment:1; /* Byte 15 Bit 3 */
boolean FastSynchronousNegotiation:1; /* Byte 15 Bit 4 */
boolean BusResetEnabled:1; /* Byte 15 Bit 5 */
boolean :1; /* Byte 15 Bit 6 */
boolean ActiveNegationEnabled:1; /* Byte 15 Bit 7 */
unsigned char BusOnDelay; /* Byte 16 */
unsigned char BusOffDelay; /* Byte 17 */
boolean HostAdapterBIOSEnabled:1; /* Byte 18 Bit 0 */
boolean BIOSRedirectionOfINT19Enabled:1; /* Byte 18 Bit 1 */
boolean ExtendedTranslationEnabled:1; /* Byte 18 Bit 2 */
boolean MapRemovableAsFixedEnabled:1; /* Byte 18 Bit 3 */
boolean :1; /* Byte 18 Bit 4 */
boolean BIOSSupportsMoreThan2DrivesEnabled:1; /* Byte 18 Bit 5 */
boolean BIOSInterruptModeEnabled:1; /* Byte 18 Bit 6 */
boolean FlopticalSupportEnabled:1; /* Byte 19 Bit 7 */
unsigned short DeviceEnabled; /* Bytes 19-20 */
unsigned short WidePermitted; /* Bytes 21-22 */
unsigned short FastPermitted; /* Bytes 23-24 */
unsigned short SynchronousPermitted; /* Bytes 25-26 */
unsigned short DisconnectPermitted; /* Bytes 27-28 */
unsigned short SendStartUnitCommand; /* Bytes 29-30 */
unsigned short IgnoreInBIOSScan; /* Bytes 31-32 */
unsigned char PCIInterruptPin:2; /* Byte 33 Bits 0-1 */
unsigned char HostAdapterIOPortAddress:2; /* Byte 33 Bits 2-3 */
boolean StrictRoundRobinModeEnabled:1; /* Byte 33 Bit 4 */
boolean VESABusSpeedGreaterThan33MHz:1; /* Byte 33 Bit 5 */
boolean VESABurstWriteEnabled:1; /* Byte 33 Bit 6 */
boolean VESABurstReadEnabled:1; /* Byte 33 Bit 7 */
unsigned short UltraPermitted; /* Bytes 34-35 */
unsigned int :32; /* Bytes 36-39 */
unsigned char :8; /* Byte 40 */
unsigned char AutoSCSIMaximumLUN; /* Byte 41 */
boolean :1; /* Byte 42 Bit 0 */
boolean SCAM_Dominant:1; /* Byte 42 Bit 1 */
boolean SCAM_Enabled:1; /* Byte 42 Bit 2 */
boolean SCAM_Level2:1; /* Byte 42 Bit 3 */
unsigned char :4; /* Byte 42 Bits 4-7 */
boolean INT13ExtensionEnabled:1; /* Byte 43 Bit 0 */
boolean :1; /* Byte 43 Bit 1 */
boolean CDROMBootEnabled:1; /* Byte 43 Bit 2 */
unsigned char :5; /* Byte 43 Bits 3-7 */
unsigned char BootTargetID:4; /* Byte 44 Bits 0-3 */
unsigned char BootChannel:4; /* Byte 44 Bits 4-7 */
unsigned char ForceBusDeviceScanningOrder:1; /* Byte 45 Bit 0 */
unsigned char :7; /* Byte 45 Bits 1-7 */
unsigned short NonTaggedToAlternateLUNPermitted; /* Bytes 46-47 */
unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */
unsigned char Reserved[10]; /* Bytes 50-59 */
unsigned char ManufacturingDiagnostic[2]; /* Bytes 60-61 */
unsigned short Checksum; /* Bytes 62-63 */
} }
BusLogic_AutoSCSIByte15_T; __attribute__ ((packed))
BusLogic_AutoSCSIData_T;
/* /*
Define the Host Adapter Local RAM Auto SCSI Byte 45 reply structure. Define the Host Adapter Local RAM Auto SCSI Byte 45 structure.
*/ */
typedef struct BusLogic_AutoSCSIByte45 typedef struct BusLogic_AutoSCSIByte45
...@@ -550,6 +850,22 @@ typedef struct BusLogic_AutoSCSIByte45 ...@@ -550,6 +850,22 @@ typedef struct BusLogic_AutoSCSIByte45
BusLogic_AutoSCSIByte45_T; BusLogic_AutoSCSIByte45_T;
/*
Define the Host Adapter Local RAM BIOS Drive Map Byte structure.
*/
#define BusLogic_BIOS_DriveMapOffset 17
typedef struct BusLogic_BIOSDriveMapByte
{
unsigned char TargetIDBit3:1; /* Bit 0 */
unsigned char :2; /* Bits 1-2 */
BusLogic_BIOS_DiskGeometryTranslation_T DiskGeometry:2; /* Bits 3-4 */
unsigned char TargetID:3; /* Bits 5-7 */
}
BusLogic_BIOSDriveMapByte_T;
/* /*
Define the Modify I/O Address request type. On PCI Host Adapters, the Define the Modify I/O Address request type. On PCI Host Adapters, the
Modify I/O Address command allows modification of the ISA compatible I/O Modify I/O Address command allows modification of the ISA compatible I/O
...@@ -557,33 +873,26 @@ BusLogic_AutoSCSIByte45_T; ...@@ -557,33 +873,26 @@ BusLogic_AutoSCSIByte45_T;
compliant I/O Address assigned at system initialization. compliant I/O Address assigned at system initialization.
*/ */
#define BusLogic_ModifyIO_330 0x00 typedef BusLogic_ISACompatibleIOPort_T BusLogic_ModifyIOAddressRequest_T;
#define BusLogic_ModifyIO_334 0x01
#define BusLogic_ModifyIO_230 0x02
#define BusLogic_ModifyIO_234 0x03
#define BusLogic_ModifyIO_130 0x04
#define BusLogic_ModifyIO_134 0x05
#define BusLogic_ModifyIO_Disable 0x06
#define BusLogic_ModifyIO_Disable2 0x07
typedef unsigned char BusLogic_ModifyIOAddressRequest_T;
/* /*
Define the Set CCB Format request type. 64 LUN Format CCBs are necessary to Define the Set CCB Format request type. Extended LUN Format CCBs are
support 64 Logical Units per Target Device. 8 LUN Format CCBs only support 8 necessary to support more than 8 Logical Units per Target Device.
Logical Units per Target Device.
*/ */
#define BusLogic_8LUNFormatCCB 0x00 typedef enum BusLogic_SetCCBFormatRequest
#define BusLogic_64LUNFormatCCB 0x01 {
BusLogic_LegacyLUNFormatCCB = 0,
typedef unsigned char BusLogic_SetCCBFormatRequest_T; BusLogic_ExtendedLUNFormatCCB = 1
}
__attribute__ ((packed))
BusLogic_SetCCBFormatRequest_T;
/* /*
Define the Requested Reply Length type used by the Inquire Setup Information, Define the Requested Reply Length type used by the Inquire Setup Information,
Inquire Controller Model Number, Inquire Synchronous Period, and Inquire Inquire Host Adapter Model Number, Inquire Synchronous Period, and Inquire
Extended Setup Information commands. Extended Setup Information commands.
*/ */
...@@ -591,10 +900,10 @@ typedef unsigned char BusLogic_RequestedReplyLength_T; ...@@ -591,10 +900,10 @@ typedef unsigned char BusLogic_RequestedReplyLength_T;
/* /*
Define a Lock data structure. Until a true symmetric multiprocessing kernel Define the Lock data structure. Until a true symmetric multiprocessing
with fine grained locking is available, acquiring the lock is implemented as kernel with fine grained locking is available, acquiring the lock is
saving the processor flags and disabling interrupts, and releasing the lock implemented as saving the processor flags and disabling interrupts, and
restores the saved processor flags. releasing the lock restores the saved processor flags.
*/ */
typedef unsigned long BusLogic_Lock_T; typedef unsigned long BusLogic_Lock_T;
...@@ -606,25 +915,30 @@ typedef unsigned long BusLogic_Lock_T; ...@@ -606,25 +915,30 @@ typedef unsigned long BusLogic_Lock_T;
typedef enum typedef enum
{ {
BusLogic_OutgoingMailboxFree = 0, BusLogic_OutgoingMailboxFree = 0x00,
BusLogic_MailboxStartCommand = 1, BusLogic_MailboxStartCommand = 0x01,
BusLogic_MailboxAbortCommand = 2 BusLogic_MailboxAbortCommand = 0x02
} }
__attribute__ ((packed))
BusLogic_ActionCode_T; BusLogic_ActionCode_T;
/* /*
Define the Incoming Mailbox Completion Codes. Define the Incoming Mailbox Completion Codes. The MultiMaster Firmware
only uses codes 0 - 4. The FlashPoint SCCB Manager has no mailboxes, so
completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
*/ */
typedef enum typedef enum
{ {
BusLogic_IncomingMailboxFree = 0, BusLogic_IncomingMailboxFree = 0x00,
BusLogic_CommandCompletedWithoutError = 1, BusLogic_CommandCompletedWithoutError = 0x01,
BusLogic_CommandAbortedAtHostRequest = 2, BusLogic_CommandAbortedAtHostRequest = 0x02,
BusLogic_AbortedCommandNotFound = 3, BusLogic_AbortedCommandNotFound = 0x03,
BusLogic_CommandCompletedWithError = 4 BusLogic_CommandCompletedWithError = 0x04,
BusLogic_InvalidCCB = 0x05
} }
__attribute__ ((packed))
BusLogic_CompletionCode_T; BusLogic_CompletionCode_T;
...@@ -641,6 +955,7 @@ typedef enum ...@@ -641,6 +955,7 @@ typedef enum
BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04, BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04,
BusLogic_BusDeviceReset = 0x81 BusLogic_BusDeviceReset = 0x81
} }
__attribute__ ((packed))
BusLogic_CCB_Opcode_T; BusLogic_CCB_Opcode_T;
...@@ -650,16 +965,17 @@ BusLogic_CCB_Opcode_T; ...@@ -650,16 +965,17 @@ BusLogic_CCB_Opcode_T;
typedef enum typedef enum
{ {
BusLogic_UncheckedDataTransfer = 0x00, BusLogic_UncheckedDataTransfer = 0,
BusLogic_DataInLengthChecked = 0x01, BusLogic_DataInLengthChecked = 1,
BusLogic_DataOutLengthChecked = 0x02, BusLogic_DataOutLengthChecked = 2,
BusLogic_NoDataTransfer = 0x03 BusLogic_NoDataTransfer = 3
} }
BusLogic_DataDirection_T; BusLogic_DataDirection_T;
/* /*
Define the Host Adapter Status Codes. Define the Host Adapter Status Codes. The MultiMaster Firmware does not
return status code 0x0C; it uses 0x12 for both overruns and underruns.
*/ */
typedef enum typedef enum
...@@ -667,8 +983,9 @@ typedef enum ...@@ -667,8 +983,9 @@ typedef enum
BusLogic_CommandCompletedNormally = 0x00, BusLogic_CommandCompletedNormally = 0x00,
BusLogic_LinkedCommandCompleted = 0x0A, BusLogic_LinkedCommandCompleted = 0x0A,
BusLogic_LinkedCommandCompletedWithFlag = 0x0B, BusLogic_LinkedCommandCompletedWithFlag = 0x0B,
BusLogic_DataUnderRun = 0x0C,
BusLogic_SCSISelectionTimeout = 0x11, BusLogic_SCSISelectionTimeout = 0x11,
BusLogic_DataOverUnderRun = 0x12, BusLogic_DataOverRun = 0x12,
BusLogic_UnexpectedBusFree = 0x13, BusLogic_UnexpectedBusFree = 0x13,
BusLogic_InvalidBusPhaseRequested = 0x14, BusLogic_InvalidBusPhaseRequested = 0x14,
BusLogic_InvalidOutgoingMailboxActionCode = 0x15, BusLogic_InvalidOutgoingMailboxActionCode = 0x15,
...@@ -689,6 +1006,7 @@ typedef enum ...@@ -689,6 +1006,7 @@ typedef enum
BusLogic_HostAdapterHardwareTimeoutError = 0x30, BusLogic_HostAdapterHardwareTimeoutError = 0x30,
BusLogic_SCSIParityErrorDetected = 0x34 BusLogic_SCSIParityErrorDetected = 0x34
} }
__attribute__ ((packed))
BusLogic_HostAdapterStatus_T; BusLogic_HostAdapterStatus_T;
...@@ -702,6 +1020,7 @@ typedef enum ...@@ -702,6 +1020,7 @@ typedef enum
BusLogic_CheckCondition = 0x02, BusLogic_CheckCondition = 0x02,
BusLogic_DeviceBusy = 0x08 BusLogic_DeviceBusy = 0x08
} }
__attribute__ ((packed))
BusLogic_TargetDeviceStatus_T; BusLogic_TargetDeviceStatus_T;
...@@ -711,10 +1030,10 @@ BusLogic_TargetDeviceStatus_T; ...@@ -711,10 +1030,10 @@ BusLogic_TargetDeviceStatus_T;
typedef enum typedef enum
{ {
BusLogic_SimpleQueueTag = 0x00, BusLogic_SimpleQueueTag = 0,
BusLogic_HeadOfQueueTag = 0x01, BusLogic_HeadOfQueueTag = 1,
BusLogic_OrderedQueueTag = 0x02, BusLogic_OrderedQueueTag = 2,
BusLogic_ReservedQT = 0x03 BusLogic_ReservedQT = 3
} }
BusLogic_QueueTag_T; BusLogic_QueueTag_T;
...@@ -729,59 +1048,75 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength]; ...@@ -729,59 +1048,75 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength];
/* /*
Define the Scatter/Gather Segment structure required by the Host Adapter Define the Scatter/Gather Segment structure required by the MultiMaster
Firmware Interface. Firmware Interface and the FlashPoint SCCB Manager.
*/ */
typedef struct BusLogic_ScatterGatherSegment typedef struct BusLogic_ScatterGatherSegment
{ {
unsigned int SegmentByteCount; /* Bytes 0-3 */ BusLogic_ByteCount_T SegmentByteCount; /* Bytes 0-3 */
bus_address_t SegmentDataPointer; /* Bytes 4-7 */ BusLogic_BusAddress_T SegmentDataPointer; /* Bytes 4-7 */
} }
BusLogic_ScatterGatherSegment_T; BusLogic_ScatterGatherSegment_T;
/* /*
Define the 32 Bit Mode Command Control Block (CCB) structure. The first 40 Define the 32 Bit Mode Command Control Block (CCB) structure. The first 40
bytes are defined by the Host Adapter Firmware Interface. The remaining bytes are defined by and common to both the MultiMaster Firmware and the
components are defined by the Linux BusLogic Driver. 64 LUN Format CCBs FlashPoint SCCB Manager. The next 60 bytes are defined by the FlashPoint
differ from standard 8 LUN Format 32 Bit Mode CCBs only in having the SCCB Manager. The remaining components are defined by the Linux BusLogic
TagEnable and QueueTag fields moved from byte 17 to byte 1, and the Logical Driver. Extended LUN Format CCBs differ from Legacy LUN Format 32 Bit Mode
Unit field in byte 17 expanded to 6 bits; unfortunately, using a union of CCBs only in having the TagEnable and QueueTag fields moved from byte 17 to
structs containing enumeration type bitfields to provide both definitions byte 1, and the Logical Unit field in byte 17 expanded to 6 bits. In theory,
leads to packing problems, so the following definition is used which requires Extended LUN Format CCBs can support up to 64 Logical Units, but in practice
setting TagEnable to Logical Unit bit 5 in 64 LUN Format CCBs. many devices will respond improperly to Logical Units between 32 and 63, and
the SCSI-2 specification defines Bit 5 as LUNTAR. Extended LUN Format CCBs
are used by recent versions of the MultiMaster Firmware, as well as by the
FlashPoint SCCB Manager; the FlashPoint SCCB Manager only supports 32 Logical
Units. Since 64 Logical Units are unlikely to be needed in practice, and
since they are problematic for the above reasons, and since limiting them to
5 bits simplifies the CCB structure definition, this driver only supports
32 Logical Units per Target Device.
*/ */
typedef struct BusLogic_CCB typedef struct BusLogic_CCB
{ {
/* /*
BusLogic Host Adapter Firmware Portion. MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
*/ */
BusLogic_CCB_Opcode_T Opcode:8; /* Byte 0 */ BusLogic_CCB_Opcode_T Opcode; /* Byte 0 */
unsigned char :3; /* Byte 1 Bits 0-2 */ unsigned char :3; /* Byte 1 Bits 0-2 */
BusLogic_DataDirection_T DataDirection:2; /* Byte 1 Bits 3-4 */ BusLogic_DataDirection_T DataDirection:2; /* Byte 1 Bits 3-4 */
boolean TagEnable64LUN:1; /* Byte 1 Bit 5 */ boolean TagEnable:1; /* Byte 1 Bit 5 */
BusLogic_QueueTag_T QueueTag64LUN:2; /* Byte 1 Bits 6-7 */ BusLogic_QueueTag_T QueueTag:2; /* Byte 1 Bits 6-7 */
unsigned char CDB_Length; /* Byte 2 */ unsigned char CDB_Length; /* Byte 2 */
unsigned char SenseDataLength; /* Byte 3 */ unsigned char SenseDataLength; /* Byte 3 */
unsigned int DataLength; /* Bytes 4-7 */ BusLogic_ByteCount_T DataLength; /* Bytes 4-7 */
bus_address_t DataPointer; /* Bytes 8-11 */ BusLogic_BusAddress_T DataPointer; /* Bytes 8-11 */
unsigned char :8; /* Byte 12 */ unsigned char :8; /* Byte 12 */
unsigned char :8; /* Byte 13 */ unsigned char :8; /* Byte 13 */
BusLogic_HostAdapterStatus_T HostAdapterStatus:8; /* Byte 14 */ BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 14 */
BusLogic_TargetDeviceStatus_T TargetDeviceStatus:8; /* Byte 15 */ BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* Byte 15 */
unsigned char TargetID; /* Byte 16 */ unsigned char TargetID; /* Byte 16 */
unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */ unsigned char LogicalUnit:5; /* Byte 17 Bits 0-4 */
boolean TagEnable:1; /* Byte 17 Bit 5 */ boolean LegacyTagEnable:1; /* Byte 17 Bit 5 */
BusLogic_QueueTag_T QueueTag:2; /* Byte 17 Bits 6-7 */ BusLogic_QueueTag_T LegacyQueueTag:2; /* Byte 17 Bits 6-7 */
SCSI_CDB_T CDB; /* Bytes 18-29 */ SCSI_CDB_T CDB; /* Bytes 18-29 */
unsigned char :8; /* Byte 30 */ unsigned char :8; /* Byte 30 */
unsigned char :8; /* Byte 31 */ unsigned char :8; /* Byte 31 */
unsigned int :32; /* Bytes 32-35 */ unsigned int :32; /* Bytes 32-35 */
bus_address_t SenseDataPointer; /* Bytes 36-39 */ BusLogic_BusAddress_T SenseDataPointer; /* Bytes 36-39 */
/* /*
BusLogic Linux Driver Portion. FlashPoint SCCB Manager Defined Portion.
*/
void (*CallbackFunction)(struct BusLogic_CCB *); /* Bytes 40-43 */
BusLogic_IO_Address_T BaseAddress; /* Bytes 44-47 */
BusLogic_CompletionCode_T CompletionCode; /* Byte 48 */
unsigned char :8; /* Byte 49 */
unsigned short OS_Flags; /* Bytes 50-51 */
unsigned char Private[48]; /* Bytes 52-99 */
/*
BusLogic Linux Driver Defined Portion.
*/ */
struct BusLogic_HostAdapter *HostAdapter; struct BusLogic_HostAdapter *HostAdapter;
SCSI_Command_T *Command; SCSI_Command_T *Command;
...@@ -789,13 +1124,13 @@ typedef struct BusLogic_CCB ...@@ -789,13 +1124,13 @@ typedef struct BusLogic_CCB
BusLogic_CCB_Active = 1, BusLogic_CCB_Active = 1,
BusLogic_CCB_Completed = 2, BusLogic_CCB_Completed = 2,
BusLogic_CCB_Reset = 3 } Status; BusLogic_CCB_Reset = 3 } Status;
BusLogic_CompletionCode_T MailboxCompletionCode;
unsigned long SerialNumber; unsigned long SerialNumber;
struct BusLogic_CCB *Next; struct BusLogic_CCB *Next;
struct BusLogic_CCB *NextAll; struct BusLogic_CCB *NextAll;
BusLogic_ScatterGatherSegment_T BusLogic_ScatterGatherSegment_T
ScatterGatherList[BusLogic_ScatterGatherLimit]; ScatterGatherList[BusLogic_ScatterGatherLimit];
} }
__attribute__ ((packed))
BusLogic_CCB_T; BusLogic_CCB_T;
...@@ -805,9 +1140,9 @@ BusLogic_CCB_T; ...@@ -805,9 +1140,9 @@ BusLogic_CCB_T;
typedef struct BusLogic_OutgoingMailbox typedef struct BusLogic_OutgoingMailbox
{ {
bus_address_t CCB; /* Bytes 0-3 */ BusLogic_BusAddress_T CCB; /* Bytes 0-3 */
unsigned int :24; /* Byte 4 */ unsigned int :24; /* Bytes 4-6 */
BusLogic_ActionCode_T ActionCode:8; /* Bytes 5-7 */ BusLogic_ActionCode_T ActionCode; /* Byte 7 */
} }
BusLogic_OutgoingMailbox_T; BusLogic_OutgoingMailbox_T;
...@@ -818,50 +1153,112 @@ BusLogic_OutgoingMailbox_T; ...@@ -818,50 +1153,112 @@ BusLogic_OutgoingMailbox_T;
typedef struct BusLogic_IncomingMailbox typedef struct BusLogic_IncomingMailbox
{ {
bus_address_t CCB; /* Bytes 0-3 */ BusLogic_BusAddress_T CCB; /* Bytes 0-3 */
BusLogic_HostAdapterStatus_T HostAdapterStatus:8; /* Byte 4 */ BusLogic_HostAdapterStatus_T HostAdapterStatus; /* Byte 4 */
BusLogic_TargetDeviceStatus_T TargetDeviceStatus:8; /* Byte 5 */ BusLogic_TargetDeviceStatus_T TargetDeviceStatus; /* Byte 5 */
unsigned char :8; /* Byte 6 */ unsigned char :8; /* Byte 6 */
BusLogic_CompletionCode_T CompletionCode:8; /* Byte 7 */ BusLogic_CompletionCode_T CompletionCode; /* Byte 7 */
} }
BusLogic_IncomingMailbox_T; BusLogic_IncomingMailbox_T;
/* /*
Define the possible Bus Types. Define the Linux BusLogic Driver Command Line Entry structure.
*/ */
typedef enum typedef struct BusLogic_CommandLineEntry
{ {
BusLogic_Unknown_Bus = 0, BusLogic_IO_Address_T IO_Address;
BusLogic_ISA_Bus = 1, unsigned short TaggedQueueDepth;
BusLogic_MCA_Bus = 2, unsigned short BusSettleTime;
BusLogic_EISA_Bus = 3, unsigned short TaggedQueuingPermitted;
BusLogic_VESA_Bus = 4, unsigned short TaggedQueuingPermittedMask;
BusLogic_PCI_Bus = 5 BusLogic_LocalOptions_T LocalOptions;
BusLogic_ErrorRecoveryStrategy_T
ErrorRecoveryStrategy[BusLogic_MaxTargetDevices];
} }
BusLogic_BusType_T; BusLogic_CommandLineEntry_T;
static char
*BusLogic_BusNames[] = /*
{ "Unknown", "ISA", "MCA", "EISA", "VESA", "PCI" }; Define the Host Adapter Target Device Statistics structure.
*/
#define BusLogic_SizeBuckets 10
typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
typedef struct BusLogic_TargetDeviceStatistics
{
unsigned int CommandsAttempted;
unsigned int CommandsCompleted;
unsigned int ReadCommands;
unsigned int WriteCommands;
BusLogic_ByteCounter_T TotalBytesRead;
BusLogic_ByteCounter_T TotalBytesWritten;
BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
unsigned short CommandAbortsRequested;
unsigned short CommandAbortsAttempted;
unsigned short CommandAbortsCompleted;
unsigned short BusDeviceResetsRequested;
unsigned short BusDeviceResetsAttempted;
unsigned short BusDeviceResetsCompleted;
unsigned short HostAdapterResetsRequested;
unsigned short HostAdapterResetsAttempted;
unsigned short HostAdapterResetsCompleted;
}
BusLogic_TargetDeviceStatistics_T;
/* /*
Define the Linux BusLogic Driver Command Line Entry structure. Define the FlashPoint Card Handle data type.
*/ */
typedef struct BusLogic_CommandLineEntry #define FlashPoint_BadCardHandle 0xFFFFFFFF
typedef unsigned int FlashPoint_CardHandle_T;
/*
Define the FlashPoint Information structure. This structure is defined
by the FlashPoint SCCB Manager.
*/
typedef struct FlashPoint_Info
{ {
unsigned int IO_Address; BusLogic_IO_Address_T BaseAddress; /* Bytes 0-3 */
unsigned short TaggedQueueDepth; boolean Present; /* Byte 4 */
unsigned short BusSettleTime; unsigned char IRQ_Channel; /* Byte 5 */
unsigned short LocalOptions; unsigned char SCSI_ID; /* Byte 6 */
unsigned short TaggedQueuingPermitted; unsigned char SCSI_LUN; /* Byte 7 */
unsigned short TaggedQueuingPermittedMask; unsigned short FirmwareRevision; /* Bytes 8-9 */
unsigned char ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; unsigned short SynchronousPermitted; /* Bytes 10-11 */
unsigned short FastPermitted; /* Bytes 12-13 */
unsigned short UltraPermitted; /* Bytes 14-15 */
unsigned short DisconnectPermitted; /* Bytes 16-17 */
unsigned short WidePermitted; /* Bytes 18-19 */
boolean ParityCheckingEnabled:1; /* Byte 20 Bit 0 */
boolean HostWideSCSI:1; /* Byte 20 Bit 1 */
boolean HostSoftReset:1; /* Byte 20 Bit 2 */
boolean ExtendedTranslationEnabled:1; /* Byte 20 Bit 3 */
boolean LowByteTerminated:1; /* Byte 20 Bit 4 */
boolean HighByteTerminated:1; /* Byte 20 Bit 5 */
boolean ReportDataUnderrun:1; /* Byte 20 Bit 6 */
boolean SCAM_Enabled:1; /* Byte 20 Bit 7 */
boolean SCAM_Level2:1; /* Byte 21 Bit 0 */
unsigned char :7; /* Byte 21 Bits 1-7 */
unsigned char Family; /* Byte 22 */
unsigned char BusType; /* Byte 23 */
unsigned char ModelNumber[3]; /* Bytes 24-26 */
unsigned char RelativeCardNumber; /* Byte 27 */
unsigned char Reserved[4]; /* Bytes 28-31 */
unsigned int OS_Reserved; /* Bytes 32-35 */
unsigned char TranslationInfo[4]; /* Bytes 36-39 */
unsigned int Reserved2[5]; /* Bytes 40-59 */
unsigned int SecondaryRange; /* Bytes 60-63 */
} }
BusLogic_CommandLineEntry_T; FlashPoint_Info_T;
/* /*
...@@ -871,32 +1268,40 @@ BusLogic_CommandLineEntry_T; ...@@ -871,32 +1268,40 @@ BusLogic_CommandLineEntry_T;
typedef struct BusLogic_HostAdapter typedef struct BusLogic_HostAdapter
{ {
SCSI_Host_T *SCSI_Host; SCSI_Host_T *SCSI_Host;
unsigned int IO_Address; BusLogic_IO_Address_T IO_Address;
BusLogic_PCI_Address_T PCI_Address;
unsigned short AddressCount;
unsigned char HostNumber; unsigned char HostNumber;
unsigned char ModelName[9]; unsigned char ModelName[9];
unsigned char FirmwareVersion[6]; unsigned char FirmwareVersion[6];
unsigned char ControllerName[18]; unsigned char FullModelName[18];
unsigned char InterruptLabel[62]; unsigned char InterruptLabel[68];
unsigned char IRQ_Channel; unsigned char IRQ_Channel;
unsigned char DMA_Channel; unsigned char DMA_Channel;
unsigned char SCSI_ID; unsigned char SCSI_ID;
BusLogic_BusType_T BusType:3; unsigned char Bus;
unsigned char Device;
BusLogic_HostAdapterType_T HostAdapterType;
BusLogic_HostAdapterBusType_T HostAdapterBusType:3;
boolean IRQ_ChannelAcquired:1; boolean IRQ_ChannelAcquired:1;
boolean DMA_ChannelAcquired:1; boolean DMA_ChannelAcquired:1;
boolean SynchronousInitiation:1; boolean ExtendedTranslationEnabled:1;
boolean ParityChecking:1; boolean ParityCheckingEnabled:1;
boolean ExtendedTranslation:1; boolean BusResetEnabled;
boolean LevelSensitiveInterrupts:1; boolean LevelSensitiveInterrupt:1;
boolean HostWideSCSI:1; boolean HostWideSCSI:1;
boolean HostDifferentialSCSI:1; boolean HostDifferentialSCSI:1;
boolean HostAutomaticConfiguration:1; boolean HostSupportsSCAM:1;
boolean HostUltraSCSI:1; boolean HostUltraSCSI:1;
boolean ExtendedLUNSupport:1;
boolean TerminationInfoValid:1; boolean TerminationInfoValid:1;
boolean LowByteTerminated:1; boolean LowByteTerminated:1;
boolean HighByteTerminated:1; boolean HighByteTerminated:1;
boolean BounceBuffersRequired:1; boolean BounceBuffersRequired:1;
boolean StrictRoundRobinModeSupport:1; boolean StrictRoundRobinModeSupport:1;
boolean Host64LUNSupport:1; boolean SCAM_Enabled:1;
boolean SCAM_Level2:1;
boolean HostAdapterInitialized;
boolean HostAdapterResetRequested:1; boolean HostAdapterResetRequested:1;
volatile boolean HostAdapterCommandCompleted:1; volatile boolean HostAdapterCommandCompleted:1;
unsigned short HostAdapterScatterGatherLimit; unsigned short HostAdapterScatterGatherLimit;
...@@ -906,27 +1311,40 @@ typedef struct BusLogic_HostAdapter ...@@ -906,27 +1311,40 @@ typedef struct BusLogic_HostAdapter
unsigned short MailboxCount; unsigned short MailboxCount;
unsigned short InitialCCBs; unsigned short InitialCCBs;
unsigned short IncrementalCCBs; unsigned short IncrementalCCBs;
unsigned short TotalQueueDepth; unsigned short DriverQueueDepth;
unsigned short HostAdapterQueueDepth;
unsigned short TaggedQueueDepth; unsigned short TaggedQueueDepth;
unsigned short UntaggedQueueDepth; unsigned short UntaggedQueueDepth;
unsigned short BusSettleTime; unsigned short BusSettleTime;
unsigned short LocalOptions; unsigned short SynchronousPermitted;
unsigned short FastPermitted;
unsigned short UltraPermitted;
unsigned short WidePermitted;
unsigned short DisconnectPermitted; unsigned short DisconnectPermitted;
unsigned short TaggedQueuingPermitted; unsigned short TaggedQueuingPermitted;
bus_address_t BIOS_Address; unsigned short ExternalHostAdapterResets;
BusLogic_LocalOptions_T LocalOptions;
BusLogic_BusAddress_T BIOS_Address;
BusLogic_InstalledDevices_T InstalledDevices; BusLogic_InstalledDevices_T InstalledDevices;
BusLogic_SynchronousValues_T SynchronousValues; BusLogic_SynchronousValues_T SynchronousValues;
BusLogic_SynchronousPeriod_T SynchronousPeriod; BusLogic_SynchronousPeriod_T SynchronousPeriod;
BusLogic_CommandLineEntry_T *CommandLineEntry; BusLogic_CommandLineEntry_T *CommandLineEntry;
FlashPoint_Info_T *FlashPointInfo;
FlashPoint_CardHandle_T CardHandle;
struct BusLogic_HostAdapter *Next; struct BusLogic_HostAdapter *Next;
char *MessageBuffer;
int MessageBufferLength;
BusLogic_CCB_T *All_CCBs; BusLogic_CCB_T *All_CCBs;
BusLogic_CCB_T *Free_CCBs; BusLogic_CCB_T *Free_CCBs;
BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices]; BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
unsigned char ErrorRecoveryStrategy[BusLogic_MaxTargetDevices]; BusLogic_ErrorRecoveryStrategy_T
unsigned char TaggedQueuingActive[BusLogic_MaxTargetDevices]; ErrorRecoveryStrategy[BusLogic_MaxTargetDevices];
unsigned char CommandSuccessfulFlag[BusLogic_MaxTargetDevices]; boolean TaggedQueuingSupported[BusLogic_MaxTargetDevices];
unsigned char ActiveCommandCount[BusLogic_MaxTargetDevices]; boolean TaggedQueuingActive[BusLogic_MaxTargetDevices];
unsigned long TotalCommandCount[BusLogic_MaxTargetDevices]; boolean CommandSuccessfulFlag[BusLogic_MaxTargetDevices];
unsigned char QueueDepth[BusLogic_MaxTargetDevices];
unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
unsigned long LastSequencePoint[BusLogic_MaxTargetDevices]; unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
unsigned long LastResetTime[BusLogic_MaxTargetDevices]; unsigned long LastResetTime[BusLogic_MaxTargetDevices];
BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox; BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox;
...@@ -935,6 +1353,7 @@ typedef struct BusLogic_HostAdapter ...@@ -935,6 +1353,7 @@ typedef struct BusLogic_HostAdapter
BusLogic_IncomingMailbox_T *FirstIncomingMailbox; BusLogic_IncomingMailbox_T *FirstIncomingMailbox;
BusLogic_IncomingMailbox_T *LastIncomingMailbox; BusLogic_IncomingMailbox_T *LastIncomingMailbox;
BusLogic_IncomingMailbox_T *NextIncomingMailbox; BusLogic_IncomingMailbox_T *NextIncomingMailbox;
BusLogic_TargetDeviceStatistics_T *TargetDeviceStatistics;
} }
BusLogic_HostAdapter_T; BusLogic_HostAdapter_T;
...@@ -1007,42 +1426,78 @@ void BusLogic_ReleaseHostAdapterLockID(BusLogic_HostAdapter_T *HostAdapter, ...@@ -1007,42 +1426,78 @@ void BusLogic_ReleaseHostAdapterLockID(BusLogic_HostAdapter_T *HostAdapter,
*/ */
static inline static inline
void BusLogic_WriteControlRegister(BusLogic_HostAdapter_T *HostAdapter, void BusLogic_SCSIBusReset(BusLogic_HostAdapter_T *HostAdapter)
unsigned char Value) {
BusLogic_ControlRegister_T ControlRegister;
ControlRegister.All = 0;
ControlRegister.Bits.SCSIBusReset = true;
outb(ControlRegister.All,
HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
}
static inline
void BusLogic_InterruptReset(BusLogic_HostAdapter_T *HostAdapter)
{
BusLogic_ControlRegister_T ControlRegister;
ControlRegister.All = 0;
ControlRegister.Bits.InterruptReset = true;
outb(ControlRegister.All,
HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
}
static inline
void BusLogic_SoftReset(BusLogic_HostAdapter_T *HostAdapter)
{ {
outb(Value, HostAdapter->IO_Address + BusLogic_ControlRegister); BusLogic_ControlRegister_T ControlRegister;
ControlRegister.All = 0;
ControlRegister.Bits.SoftReset = true;
outb(ControlRegister.All,
HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
}
static inline
void BusLogic_HardReset(BusLogic_HostAdapter_T *HostAdapter)
{
BusLogic_ControlRegister_T ControlRegister;
ControlRegister.All = 0;
ControlRegister.Bits.HardReset = true;
outb(ControlRegister.All,
HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
} }
static inline static inline
unsigned char BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter) unsigned char BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter)
{ {
return inb(HostAdapter->IO_Address + BusLogic_StatusRegister); return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
} }
static inline static inline
void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T *HostAdapter, void BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T
*HostAdapter,
unsigned char Value) unsigned char Value)
{ {
outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegister); outb(Value,
HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
} }
static inline static inline
unsigned char BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter) unsigned char BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter)
{ {
return inb(HostAdapter->IO_Address + BusLogic_DataInRegister); return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
} }
static inline static inline
unsigned char BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T unsigned char BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T
*HostAdapter) *HostAdapter)
{ {
return inb(HostAdapter->IO_Address + BusLogic_InterruptRegister); return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
} }
static inline static inline
unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T *HostAdapter) unsigned char BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T
*HostAdapter)
{ {
return inb(HostAdapter->IO_Address + BusLogic_GeometryRegister); return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
} }
...@@ -1079,26 +1534,165 @@ static inline void BusLogic_Delay(int Seconds) ...@@ -1079,26 +1534,165 @@ static inline void BusLogic_Delay(int Seconds)
and PCI/VLB/EISA/ISA Bus Addresses. and PCI/VLB/EISA/ISA Bus Addresses.
*/ */
static inline bus_address_t Virtual_to_Bus(void *VirtualAddress) static inline BusLogic_BusAddress_T Virtual_to_Bus(void *VirtualAddress)
{ {
return (bus_address_t) virt_to_bus(VirtualAddress); return (BusLogic_BusAddress_T) virt_to_bus(VirtualAddress);
} }
static inline void *Bus_to_Virtual(bus_address_t BusAddress) static inline void *Bus_to_Virtual(BusLogic_BusAddress_T BusAddress)
{ {
return (void *) bus_to_virt(BusAddress); return (void *) bus_to_virt(BusAddress);
} }
/*
BusLogic_IncrementErrorCounter increments Error Counter by 1, stopping at
65535 rather than wrapping around to 0.
*/
static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
{
if (*ErrorCounter < 65535) (*ErrorCounter)++;
}
/*
BusLogic_IncrementByteCounter increments Byte Counter by Amount.
*/
static inline void BusLogic_IncrementByteCounter(BusLogic_ByteCounter_T
*ByteCounter,
unsigned int Amount)
{
ByteCounter->Units += Amount;
if (ByteCounter->Units > 999999999)
{
ByteCounter->Units -= 1000000000;
ByteCounter->Billions++;
}
}
/*
BusLogic_IncrementSizeBucket increments the Bucket for Amount.
*/
static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
CommandSizeBuckets,
unsigned int Amount)
{
int Index = 0;
if (Amount < 8*1024)
if (Amount < 2*1024)
Index = (Amount < 1*1024 ? 0 : 1);
else Index = (Amount < 4*1024 ? 2 : 3);
else if (Amount < 128*1024)
if (Amount < 32*1024)
Index = (Amount < 16*1024 ? 4 : 5);
else Index = (Amount < 64*1024 ? 6 : 7);
else Index = (Amount < 256*1024 ? 8 : 9);
CommandSizeBuckets[Index]++;
}
/*
If CONFIG_PCI is not set, force CONFIG_SCSI_OMIT_FLASHPOINT, and use the
ISA only probe function as the general one.
*/
#ifndef CONFIG_PCI
#undef CONFIG_SCSI_OMIT_FLASHPOINT
#define CONFIG_SCSI_OMIT_FLASHPOINT
#define BusLogic_InitializeProbeInfoListISA BusLogic_InitializeProbeInfoList
#endif
/*
Define macros for testing the Host Adapter Type.
*/
#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
(HostAdapter->HostAdapterType == BusLogic_MultiMaster)
#define BusLogic_FlashPointHostAdapterP(HostAdapter) \
(HostAdapter->HostAdapterType == BusLogic_FlashPoint)
#else
#define BusLogic_MultiMasterHostAdapterP(HostAdapter) \
(true)
#define BusLogic_FlashPointHostAdapterP(HostAdapter) \
(false)
#endif
/*
Define Driver Message Macros.
*/
#define BusLogic_Announce(Format, Arguments...) \
BusLogic_Message(BusLogic_AnnounceLevel, Format, ##Arguments)
#define BusLogic_Info(Format, Arguments...) \
BusLogic_Message(BusLogic_InfoLevel, Format, ##Arguments)
#define BusLogic_Notice(Format, Arguments...) \
BusLogic_Message(BusLogic_NoticeLevel, Format, ##Arguments)
#define BusLogic_Warning(Format, Arguments...) \
BusLogic_Message(BusLogic_WarningLevel, Format, ##Arguments)
#define BusLogic_Error(Format, Arguments...) \
BusLogic_Message(BusLogic_ErrorLevel, Format, ##Arguments)
/*
Define the version number of the FlashPoint Firmware (SCCB Manager).
*/
#define FlashPoint_FirmwareVersion "5.01"
/*
Define the possible return values from FlashPoint_HandleInterrupt.
*/
#define FlashPoint_NormalInterrupt 0x00
#define FlashPoint_ExternalBusReset 0xFF
/*
Define prototypes for the FlashPoint SCCB Manager Functions.
*/
extern unsigned char FlashPoint_ProbeHostAdapter(FlashPoint_Info_T *);
extern FlashPoint_CardHandle_T
FlashPoint_HardResetHostAdapter(FlashPoint_Info_T *);
extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *);
extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, BusLogic_CCB_T *);
extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
/* /*
Define prototypes for the forward referenced BusLogic Driver Define prototypes for the forward referenced BusLogic Driver
Internal Functions. Internal Functions.
*/ */
static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB);
static void BusLogic_InterruptHandler(int, void *, Registers_T *); static void BusLogic_InterruptHandler(int, void *, Registers_T *);
static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *, static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *,
SCSI_Command_T *, SCSI_Command_T *,
unsigned int); unsigned int);
static void BusLogic_Message(BusLogic_MessageLevel_T, char *Format,
BusLogic_HostAdapter_T *, ...);
#endif /* BusLogic_DriverVersion */ #endif /* BusLogic_DriverVersion */
...@@ -26,6 +26,9 @@ dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI ...@@ -26,6 +26,9 @@ dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
bool ' Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT
fi
dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
......
This source diff could not be displayed because it is too large. You can view the blob instead.
FlashPoint Driver Developer's Kit
Version 1.0
Copyright 1995-1996 by Mylex Corporation
All Rights Reserved
This program is free software; you may redistribute and/or modify it under
the terms of either:
a) the GNU General Public License as published by the Free Software
Foundation; either version 2, or (at your option) any later version,
or
b) the "BSD-style License" included below.
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 either the GNU General Public
License or the BSD-style License below 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.
The BSD-style License is as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain this LICENSE.FlashPoint
file, without modification, this list of conditions, and the following
disclaimer. The following copyright notice must appear immediately at
the beginning of all source files:
Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
This file is available under both the GNU General Public License
and a BSD-style copyright; see LICENSE.FlashPoint for details.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of Mylex Corporation may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY MYLEX CORP. ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
...@@ -381,6 +381,12 @@ endif ...@@ -381,6 +381,12 @@ endif
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
BusLogic.o: BusLogic.c FlashPoint.c
$(CC) $(CFLAGS) -c BusLogic.c -o BusLogic.O
$(CC) $(CFLAGS) -c FlashPoint.c -o FlashPoint.O
$(LD) -r -o BusLogic.o BusLogic.O FlashPoint.O
rm -f BusLogic.O FlashPoint.O
aha152x.o: aha152x.c aha152x.o: aha152x.c
$(CC) $(CFLAGS) $(AHA152X) -c aha152x.c $(CC) $(CFLAGS) $(AHA152X) -c aha152x.c
......
BusLogic MultiMaster SCSI Driver for Linux BusLogic MultiMaster and FlashPoint SCSI Driver for Linux
Version 1.2.6 for Linux 1.2.13 Version 2.0.7 for Linux 2.0
Version 2.0.6 for Linux 2.0.4
17 July 1996 PRODUCTION RELEASE
23 February 1997
Leonard N. Zubkoff Leonard N. Zubkoff
Dandelion Digital Dandelion Digital
...@@ -18,10 +19,15 @@ BusLogic, Inc. designs and manufactures a variety of high performance SCSI host ...@@ -18,10 +19,15 @@ BusLogic, Inc. designs and manufactures a variety of high performance SCSI host
adapters which share a common programming interface across a diverse collection adapters which share a common programming interface across a diverse collection
of bus architectures by virtue of their MultiMaster ASIC technology. This of bus architectures by virtue of their MultiMaster ASIC technology. This
driver supports all present BusLogic MultiMaster Host Adapters, and should driver supports all present BusLogic MultiMaster Host Adapters, and should
support any future MultiMaster designs with little or no modification. Host support any future MultiMaster designs with little or no modification. More
adapters based on the new FlashPoint architecture are not supported by this recently, BusLogic has introduced the FlashPoint Host Adapters, which are less
driver; consult the README.FlashPoint file for information about a program to costly and rely on the host CPU, rather than including an onboard processor.
upgrade Linux users from the unsupported FlashPoint LT to the supported BT-948. Mylex/BusLogic has recently provided me with the FlashPoint Driver Developer's
Kit, which comprises documentation and freely redistributable source code for
the FlashPoint SCCB Manager. The SCCB Manager is the library of code that runs
on the host CPU and performs functions analogous to the firmware on the
MultiMaster Host Adapters. Thanks to their having provided the SCCB Manager,
this driver now supports the FlashPoint Host Adapters as well.
My primary goals in writing this completely new BusLogic driver for Linux are My primary goals in writing this completely new BusLogic driver for Linux are
to achieve the full performance that BusLogic SCSI Host Adapters and modern to achieve the full performance that BusLogic SCSI Host Adapters and modern
...@@ -112,26 +118,23 @@ o Performance Features ...@@ -112,26 +118,23 @@ o Performance Features
o Robustness Features o Robustness Features
The driver implements extensive error recovery procedures. When the higher The driver implements extensive error recovery procedures. When the higher
level parts of the SCSI subsystem request that a command be reset, action is level parts of the SCSI subsystem request that a timed out command be reset,
taken to restore proper operation of the host adapter and SCSI bus. On Linux a selection is made between a full host adapter hard reset and SCSI bus reset
1.2.13, by default a full host adapter hard reset and SCSI bus reset is versus sending a bus device reset message to the individual target device
performed. On Linux 2.0.x, by default a selection is made between a full based on the recommendation of the SCSI subsystem. Error recovery strategies
host adapter hard reset and SCSI bus reset versus sending a bus device reset are selectable from the kernel command line individually for each target
message to the individual target device based on the recommendation of the device, and also include sending a bus device reset to the specific target
SCSI subsystem. Error recovery strategies are selectable from the kernel device associated with the command being reset, as well as suppressing error
command line individually for each target device, and also include sending a recovery entirely to avoid perturbing an improperly functioning device. If
bus device reset to the specific target device associated with the command the bus device reset error recovery strategy is selected and sending a bus
being reset, as well as suppressing error recovery entirely to avoid device reset does not restore correct operation, the next command that is
perturbing an improperly functioning device. If the bus device reset error reset will force a full host adapter hard reset and SCSI bus reset. SCSI bus
recovery strategy is selected and sending a bus device reset does not restore resets caused by other devices and detected by the host adapter are also
correct operation, the next command that is reset will force a full host handled by issuing a hard reset to the host adapter and re-initialization.
adapter hard reset and SCSI bus reset. SCSI bus resets caused by other Finally, if tagged queuing is active and more than one command reset occurs
devices and detected by the host adapter are also handled by issuing a hard in a 10 minute interval, or if a command reset occurs within the first 10
reset to the host adapter and full re-initialization. Finally, if tagged minutes of operation, then tagged queuing will be disabled for that target
queuing is active and more than one command reset occurs in a 10 minute device. These error recovery options improve overall system robustness by
interval, or if a command reset occurs within the first 10 minutes of
operation, then tagged queuing will be disabled for that target device.
These error recovery options should improve overall system robustness by
preventing individual errant devices from causing the system as a whole to preventing individual errant devices from causing the system as a whole to
lock up or crash, and thereby allowing a clean shutdown and restart after the lock up or crash, and thereby allowing a clean shutdown and restart after the
offending component is removed. offending component is removed.
...@@ -155,13 +158,16 @@ o PCI Configuration Support ...@@ -155,13 +158,16 @@ o PCI Configuration Support
used to disable the ISA compatible I/O port entirely as it is not necessary. used to disable the ISA compatible I/O port entirely as it is not necessary.
The ISA compatible I/O port is disabled by default on the BT-948/958/958D. The ISA compatible I/O port is disabled by default on the BT-948/958/958D.
o /proc File System Support
Copies of the host adapter configuration information together with data
transfer and error recovery statistics are now available through the
/proc/scsi/BusLogic/<N> interface.
o Shared Interrupts Support o Shared Interrupts Support
On systems that support shared interrupts, any number of BusLogic Host On systems that support shared interrupts, any number of BusLogic Host
Adapters may share the same interrupt request channel, and in fact it is more Adapters may share the same interrupt request channel.
efficient if they do so. The driver scans all known BusLogic Host Adapters
whenever an interrupt is handled on an interrupt channel assigned to any
BusLogic Host Adapter.
o Wide SCSI Support o Wide SCSI Support
...@@ -181,13 +187,20 @@ the date of this document. It is recommended that anyone purchasing a BusLogic ...@@ -181,13 +187,20 @@ the date of this document. It is recommended that anyone purchasing a BusLogic
Host Adapter not in the following table contact the author beforehand to verify Host Adapter not in the following table contact the author beforehand to verify
that it is or will be supported. that it is or will be supported.
"W" Series Host Adapters: FlashPoint Series PCI Host Adapters:
FlashPoint LT (BT-930) Ultra Fast Single-ended SCSI-2
FlashPoint DL (BT-932) Dual Channel Ultra Fast Single-ended SCSI-2
FlashPoint LW (BT-950) Ultra Wide Single-ended SCSI-2
FlashPoint DW (BT-952) Dual Channel Ultra Wide Single-ended SCSI-2
MultiMaster "W" Series Host Adapters:
BT-948 PCI Ultra Fast Single-ended SCSI-2 BT-948 PCI Ultra Fast Single-ended SCSI-2
BT-958 PCI Ultra Wide Single-ended SCSI-2 BT-958 PCI Ultra Wide Single-ended SCSI-2
BT-958D PCI Ultra Wide Differential SCSI-2 BT-958D PCI Ultra Wide Differential SCSI-2
"C" Series Host Adapters: MultiMaster "C" Series Host Adapters:
BT-946C PCI Fast Single-ended SCSI-2 BT-946C PCI Fast Single-ended SCSI-2
BT-956C PCI Fast Wide Single-ended SCSI-2 BT-956C PCI Fast Wide Single-ended SCSI-2
...@@ -199,7 +212,7 @@ BT-757CD EISA Fast Wide Differential SCSI-2 ...@@ -199,7 +212,7 @@ BT-757CD EISA Fast Wide Differential SCSI-2
BT-545C ISA Fast Single-ended SCSI-2 BT-545C ISA Fast Single-ended SCSI-2
BT-540CF ISA Fast Single-ended SCSI-2 BT-540CF ISA Fast Single-ended SCSI-2
"S" Series Host Adapters: MultiMaster "S" Series Host Adapters:
BT-445S VLB Fast Single-ended SCSI-2 BT-445S VLB Fast Single-ended SCSI-2
BT-747S EISA Fast Single-ended SCSI-2 BT-747S EISA Fast Single-ended SCSI-2
...@@ -211,18 +224,13 @@ BT-542D ISA Fast Differential SCSI-2 ...@@ -211,18 +224,13 @@ BT-542D ISA Fast Differential SCSI-2
BT-742A EISA Single-ended SCSI-2 (742A revision H) BT-742A EISA Single-ended SCSI-2 (742A revision H)
BT-542B ISA Single-ended SCSI-2 (542B revision H) BT-542B ISA Single-ended SCSI-2 (542B revision H)
"A" Series Host Adapters: MultiMaster "A" Series Host Adapters:
BT-742A EISA Single-ended SCSI-2 (742A revisions A - G) BT-742A EISA Single-ended SCSI-2 (742A revisions A - G)
BT-542B ISA Single-ended SCSI-2 (542B revisions A - G) BT-542B ISA Single-ended SCSI-2 (542B revisions A - G)
The FlashPoint LT, also known as the BT-930 Ultra, implements a different host AMI FastDisk Host Adapters that are true BusLogic MultiMaster clones are also
interface and is not supported by this driver. Consult the README.FlashPoint supported by this driver.
file for information about a program to upgrade Linux users from the
unsupported FlashPoint LT to the supported BT-948.
AMI FastDisk Host Adapters that are true BusLogic clones are supported by this
driver.
BT-948/958/958D INSTALLATION NOTES BT-948/958/958D INSTALLATION NOTES
...@@ -285,6 +293,45 @@ kernel command line options. A full description of the command line options ...@@ -285,6 +293,45 @@ kernel command line options. A full description of the command line options
may be found in the comments before BusLogic_Setup in the kernel source code may be found in the comments before BusLogic_Setup in the kernel source code
file "BusLogic.c". The following examples may be useful as a starting point: file "BusLogic.c". The following examples may be useful as a starting point:
"BusLogic=NoProbe"
No probing of any kind is to be performed, and hence no BusLogic Host
Adapters will be detected.
"BusLogic=NoProbeISA"
No probing of the standard ISA I/O Addresses will be done, and hence only
PCI Host Adapters will be detected.
"BusLogic=NoProbePCI"
No interrogation of PCI Configuration Space will be made, and hence only
ISA Multimaster Host Adapters will be detected, as well as PCI Multimaster
Host Adapters that have their ISA Compatible I/O Port set to "Primary" or
"Alternate".
"BusLogic=NoSortPCI"
PCI MultiMaster Host Adapters will be enumerated in the order provided by
the PCI BIOS, ignoring any setting of the AutoSCSI "Use Bus And Device #
For PCI Scanning Seq." option.
"BusLogic=MultiMasterFirst"
By default, if both FlashPoint and PCI MultiMaster Host Adapters are
present, this driver will probe for PCI MultiMaster Host Adapters first
unless the BIOS primary disk is not controlled by the first PCI MultiMaster
Host Adapter, in which case FlashPoint Host Adapters will be probed first.
This option forces MultiMaster Host Adapters to be probed first.
"BusLogic=FlashPointFirst"
By default, if both FlashPoint and PCI MultiMaster Host Adapters are
present, this driver will probe for PCI MultiMaster Host Adapters first
unless the BIOS primary disk is not controlled by the first PCI MultiMaster
Host Adapter, in which case FlashPoint Host Adapters will be probed first.
This option forces FlashPoint Host Adapters to be probed first.
"BusLogic=0x330" "BusLogic=0x330"
This command line limits probing to the single I/O port at 0x330. This command line limits probing to the single I/O port at 0x330.
...@@ -295,10 +342,11 @@ file "BusLogic.c". The following examples may be useful as a starting point: ...@@ -295,10 +342,11 @@ file "BusLogic.c". The following examples may be useful as a starting point:
which also disables tagged queuing. It may be useful if problems arise which also disables tagged queuing. It may be useful if problems arise
during installation on a system with a flaky SCSI configuration. In cases during installation on a system with a flaky SCSI configuration. In cases
of a marginal SCSI configuration it may also be beneficial to disable fast of a marginal SCSI configuration it may also be beneficial to disable fast
transfers and/or synchronous negotiation using AutoSCSI on "W" and "C" transfers and/or synchronous negotiation using AutoSCSI on FlashPoint and
series controllers. Disconnect/reconnect may also be disabled for fast "W" and "C" series MultiMaster host adapters. Disconnect/reconnect may
devices such as disk drives, but should not be disabled for tape drives or also be disabled for fast devices such as disk drives, but should not be
other devices where a single command may take over a second to execute. disabled for tape drives or other devices where a single command may take
over a second to execute.
"BusLogic=0,0,30" "BusLogic=0,0,30"
...@@ -325,21 +373,16 @@ substantially impact performance. ...@@ -325,21 +373,16 @@ substantially impact performance.
INSTALLATION INSTALLATION
This distribution was prepared for Linux kernel version 1.2.13 This distribution was prepared for Linux kernel version 2.0.29, but should be
(BusLogic-1.2.6.tar.gz) or Linux kernel version 2.0.4 (BusLogic-2.0.6.tar.gz). compatible with 2.0.4 or any later 2.0 series kernel.
Installation in later versions will probably be successful as well, though
BusLogic.patch may not be required. Installation in earlier versions is not
recommended.
To install the BusLogic SCSI driver, you may use the following commands, To install the new BusLogic SCSI driver, you may use the following commands,
replacing "/usr/src" with wherever you keep your Linux kernel source tree replacing "/usr/src" with wherever you keep your Linux kernel source tree:
(substitute "1.2" or "2.0" for "x.y" in the tar command as appropriate):
cd /usr/src cd /usr/src
tar -xvzf BusLogic-x.y.6.tar.gz tar -xvzf BusLogic-2.0.7.tar.gz
mv README.* BusLogic.[ch] linux/drivers/scsi mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi
patch -p < BusLogic.patch (on Linux 1.2.13 only) patch -p < BusLogic.patch
patch -p < BusLogic.elf_patch (on Linux 1.2.13 ELF systems only)
cd linux cd linux
make config make config
make depend make depend
......
The BusLogic FlashPoint SCSI host adapters are now supported on Linux 2.0.x. The BusLogic FlashPoint SCSI Host Adapters are now supported on Linux. The
See http://www.dandelion.com/Linux/ for the beta test BusLogic driver which upgrade program described below will remain available through March 1997.
includes FlashPoint support. The upgrade program described below will remain
available through the end of 1996.
......
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
* controller). * controller).
* Modified by Matti Aarnio * Modified by Matti Aarnio
* Accept parameters from LILO cmd-line. -- 1-Oct-94 * Accept parameters from LILO cmd-line. -- 1-Oct-94
* Modified by Mike McLagan <mike.mclagan@linux.org>
* Recognise extended mode on AHA1542CP, different bit than 1542CF
* 1-Jan-97
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -813,7 +816,9 @@ static int aha1542_mbenable(int base) ...@@ -813,7 +816,9 @@ static int aha1542_mbenable(int base)
mbenable_cmd[0]=CMD_MBENABLE; mbenable_cmd[0]=CMD_MBENABLE;
mbenable_cmd[1]=0; mbenable_cmd[1]=0;
mbenable_cmd[2]=mbenable_result[1]; mbenable_cmd[2]=mbenable_result[1];
if(mbenable_result[1] & 1) retval = BIOS_TRANSLATION_25563;
if(mbenable_result[1] & 0x03) retval = BIOS_TRANSLATION_25563;
aha1542_out(base,mbenable_cmd,3); aha1542_out(base,mbenable_cmd,3);
WAIT(INTRFLAGS(base),INTRMASK,HACC,0); WAIT(INTRFLAGS(base),INTRMASK,HACC,0);
}; };
......
...@@ -247,8 +247,12 @@ static int ioctl_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic) ...@@ -247,8 +247,12 @@ static int ioctl_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
retries = 1; retries = 1;
break; break;
case START_STOP: case START_STOP:
timeout = 2 * 60 * HZ; /* 2 minutes */
retries = 1;
break;
case MOVE_MEDIUM: case MOVE_MEDIUM:
timeout = 60 * HZ; /* 60 seconds */ case READ_ELEMENT_STATUS:
timeout = 5 * 60 * HZ; /* 5 minutes */
retries = 1; retries = 1;
break; break;
default: default:
......
...@@ -1210,6 +1210,7 @@ static int sd_init_onedisk(int i) ...@@ -1210,6 +1210,7 @@ static int sd_init_onedisk(int i)
printk ("scsi : deleting disk entry.\n"); printk ("scsi : deleting disk entry.\n");
rscsi_disks[i].device = NULL; rscsi_disks[i].device = NULL;
sd_template.nr_dev--; sd_template.nr_dev--;
sd_gendisk.nr_real--;
return i; return i;
} }
} }
......
...@@ -629,7 +629,6 @@ scsi_tape_open(struct inode * inode, struct file * filp) ...@@ -629,7 +629,6 @@ scsi_tape_open(struct inode * inode, struct file * filp)
if ((STp->buffer)->last_result_fatal != 0) { if ((STp->buffer)->last_result_fatal != 0) {
if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 && if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
(SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) { (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE) {
printk(KERN_NOTICE "st%d: No tape.\n", dev);
STp->ready = ST_NO_TAPE; STp->ready = ST_NO_TAPE;
} else } else
STp->ready = ST_NOT_READY; STp->ready = ST_NOT_READY;
......
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
# Note 2! The CFLAGS definitions are now in the main makefile... # Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := proc.o O_TARGET := proc.o
O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
kmsg.o net.o scsi.o proc_tty.o
OX_OBJS := procfs_syms.o OX_OBJS := procfs_syms.o
M_OBJS := M_OBJS :=
......
/*
* proc/fs/generic.c --- generic routines for the proc-fs
*
* This file contains generic proc-fs routines for handling
* directories and files.
*
* Copyright (C) 1991, 1992 Linus Torvalds.
* Copyright (C) 1997 Theodore Ts'o
*/
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/config.h>
#include <asm/bitops.h>
static long proc_file_read(struct inode * inode, struct file * file,
char * buf, unsigned long nbytes);
static long proc_file_write(struct inode * inode, struct file * file,
const char * buffer, unsigned long count);
static long long proc_file_lseek(struct inode * inode, struct file * file,
long long offset, int orig);
static struct file_operations proc_file_operations = {
proc_file_lseek, /* lseek */
proc_file_read, /* read */
proc_file_write, /* write */
NULL, /* readdir */
NULL, /* poll */
NULL, /* ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* can't fsync */
};
/*
* proc files can do almost nothing..
*/
struct inode_operations proc_file_inode_operations = {
&proc_file_operations, /* default scsi directory file-ops */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
NULL /* permission */
};
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* 4K page size but our output routines use some slack for overruns */
#define PROC_BLOCK_SIZE (3*1024)
static long proc_file_read(struct inode * inode, struct file * file,
char * buf, unsigned long nbytes)
{
char *page;
int retval=0;
int n;
char *start;
struct proc_dir_entry * dp;
if (nbytes < 0)
return -EINVAL;
dp = (struct proc_dir_entry *) inode->u.generic_ip;
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
return -ENOMEM;
while (nbytes > 0)
{
n = MIN(PROC_BLOCK_SIZE, nbytes);
if (dp->get_info) {
/*
* Handle backwards compatibility with the old net
* routines.
*
* XXX What gives with the file->f_flags & O_ACCMODE
* test? Seems stupid to me....
*/
n = dp->get_info(page, &start, file->f_pos, n,
(file->f_flags & O_ACCMODE) == O_RDWR);
} else if (dp->read_proc) {
n = dp->read_proc(page, &start, file->f_pos,
n, dp->data);
} else
break;
if (n == 0)
break; /* End of file */
if (n < 0) {
if (retval == 0)
retval = n;
break;
}
n -= copy_to_user(buf, start, n);
if (n == 0) {
if (retval == 0)
retval = -EFAULT;
break;
}
file->f_pos += n; /* Move down the file */
nbytes -= n;
buf += n;
retval += n;
}
free_page((unsigned long) page);
return retval;
}
static long
proc_file_write(struct inode * inode, struct file * file,
const char * buffer, unsigned long count)
{
struct proc_dir_entry * dp;
char *page;
if (count < 0)
return -EINVAL;
dp = (struct proc_dir_entry *) inode->u.generic_ip;
if (!(page = (char*) __get_free_page(GFP_KERNEL)))
return -ENOMEM;
if (!dp->write_proc)
return -EIO;
return dp->write_proc(file, buffer, count, dp->data);
}
static long long proc_file_lseek(struct inode * inode, struct file * file,
long long offset, int orig)
{
switch (orig) {
case 0:
file->f_pos = offset;
return(file->f_pos);
case 1:
file->f_pos += offset;
return(file->f_pos);
case 2:
return(-EINVAL);
default:
return(-EINVAL);
}
}
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
{
struct proc_dir_entry *ent;
ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
if (!ent)
return NULL;
memset(ent, 0, sizeof(struct proc_dir_entry));
if (mode == S_IFDIR)
mode |= S_IRUGO | S_IXUGO;
else if (mode == 0)
mode = S_IFREG | S_IRUGO;
ent->name = name;
ent->namelen = strlen(ent->name);
ent->mode = mode;
if (S_ISDIR(mode))
ent->nlink = 2;
else
ent->nlink = 1;
if (parent)
proc_register(parent, ent);
return ent;
}
...@@ -81,6 +81,7 @@ static int parse_options(char *options,uid_t *uid,gid_t *gid) ...@@ -81,6 +81,7 @@ static int parse_options(char *options,uid_t *uid,gid_t *gid)
struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de) struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_entry * de)
{ {
struct inode * inode = iget(s, ino); struct inode * inode = iget(s, ino);
struct task_struct *p;
#ifdef CONFIG_SUN_OPENPROMFS_MODULE #ifdef CONFIG_SUN_OPENPROMFS_MODULE
if ((inode->i_ino >= PROC_OPENPROM_FIRST) if ((inode->i_ino >= PROC_OPENPROM_FIRST)
...@@ -106,6 +107,14 @@ struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_e ...@@ -106,6 +107,14 @@ struct inode * proc_get_inode(struct super_block * s, int ino, struct proc_dir_e
de->fill_inode(inode); de->fill_inode(inode);
} }
} }
/*
* Fixup the root inode's nlink value
*/
if (inode->i_ino == PROC_ROOT_INO) {
for_each_task(p)
if (p && p->pid)
inode->i_nlink++;
}
return inode; return inode;
} }
...@@ -162,93 +171,20 @@ void proc_read_inode(struct inode * inode) ...@@ -162,93 +171,20 @@ void proc_read_inode(struct inode * inode)
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_size = 0; inode->i_size = 0;
pid = ino >> 16; pid = ino >> 16;
if (!pid)
return;
p = task[0]; p = task[0];
for (i = 0; i < NR_TASKS ; i++) for (i = 0; i < NR_TASKS ; i++)
if ((p = task[i]) && (p->pid == pid)) if ((p = task[i]) && (p->pid == pid))
break; break;
if (!p || i >= NR_TASKS) if (!p || i >= NR_TASKS)
return; return;
if (ino == PROC_ROOT_INO) {
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_nlink = 2;
for (i = 1 ; i < NR_TASKS ; i++)
if (task[i])
inode->i_nlink++;
return;
}
if (!pid) {
switch (ino) {
case PROC_KMSG:
inode->i_mode = S_IFREG | S_IRUSR;
inode->i_op = &proc_kmsg_inode_operations;
break;
case PROC_NET:
inode->i_nlink = 2;
break;
case PROC_SCSI:
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
inode->i_nlink = 2;
inode->i_op = &proc_scsi_inode_operations;
break;
case PROC_KCORE:
inode->i_mode = S_IFREG | S_IRUSR;
inode->i_op = &proc_kcore_inode_operations;
inode->i_size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
break;
case PROC_PROFILE:
inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
inode->i_op = &proc_profile_inode_operations;
inode->i_size = (1+prof_len) * sizeof(unsigned long);
break;
default:
inode->i_mode = S_IFREG | S_IRUGO;
inode->i_op = &proc_array_inode_operations;
break;
}
return;
}
ino &= 0x0000ffff; ino &= 0x0000ffff;
if (ino == PROC_PID_INO || p->dumpable) { if (ino == PROC_PID_INO || p->dumpable) {
inode->i_uid = p->euid; inode->i_uid = p->euid;
inode->i_gid = p->egid; inode->i_gid = p->egid;
} }
switch (ino) {
case PROC_PID_INO:
inode->i_nlink = 4;
return;
case PROC_PID_MEM:
inode->i_op = &proc_mem_inode_operations;
inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
return;
case PROC_PID_CWD:
case PROC_PID_ROOT:
case PROC_PID_EXE:
inode->i_op = &proc_link_inode_operations;
inode->i_size = 64;
inode->i_mode = S_IFLNK | S_IRWXU;
return;
case PROC_PID_FD:
inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
inode->i_op = &proc_fd_inode_operations;
inode->i_nlink = 2;
return;
case PROC_PID_ENVIRON:
inode->i_mode = S_IFREG | S_IRUSR;
inode->i_op = &proc_array_inode_operations;
return;
case PROC_PID_CMDLINE:
case PROC_PID_STATUS:
case PROC_PID_STAT:
case PROC_PID_STATM:
inode->i_mode = S_IFREG | S_IRUGO;
inode->i_op = &proc_array_inode_operations;
return;
case PROC_PID_MAPS:
inode->i_mode = S_IFIFO | S_IRUGO;
inode->i_op = &proc_arraylong_inode_operations;
return;
}
switch (ino >> 8) { switch (ino >> 8) {
case PROC_PID_FD_DIR: case PROC_PID_FD_DIR:
ino &= 0xff; ino &= 0xff;
......
/*
* proc_tty.c -- handles /proc/tty
*
* Copyright 1997, Theodore Ts'o
*/
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/tty.h>
#include <linux/config.h>
#include <asm/bitops.h>
extern struct tty_driver *tty_drivers; /* linked list of tty drivers */
extern struct tty_ldisc ldiscs[];
static int tty_drivers_read_proc(char *page, char **start, off_t off,
int count, void *data);
static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
int count, void *data);
/*
* The /proc/tty directory inodes...
*/
static struct proc_dir_entry *proc_tty, *proc_tty_ldisc, *proc_tty_driver;
/*
* This is the handler for /proc/tty/drivers
*/
static int tty_drivers_read_proc(char *page, char **start, off_t off,
int count, void *data)
{
int len = 0;
off_t begin = 0;
struct tty_driver *p;
char range[20], deftype[20];
char *type;
for (p = tty_drivers; p; p = p->next) {
if (p->num > 1)
sprintf(range, "%d-%d", p->minor_start,
p->minor_start + p->num - 1);
else
sprintf(range, "%d", p->minor_start);
switch (p->type) {
case TTY_DRIVER_TYPE_SYSTEM:
if (p->subtype == SYSTEM_TYPE_TTY)
type = "system:/dev/tty";
else if (p->subtype == SYSTEM_TYPE_CONSOLE)
type = "system:console";
else
type = "system";
break;
case TTY_DRIVER_TYPE_CONSOLE:
type = "console";
break;
case TTY_DRIVER_TYPE_SERIAL:
if (p->subtype == 2)
type = "serial:callout";
else
type = "serial";
break;
case TTY_DRIVER_TYPE_PTY:
if (p->subtype == PTY_TYPE_MASTER)
type = "pty:master";
else if (p->subtype == PTY_TYPE_SLAVE)
type = "pty:slave";
else
type = "pty";
break;
default:
sprintf(deftype, "type:%d.%d", p->type, p->subtype);
type = deftype;
break;
}
len += sprintf(page+len, "%-20s /dev/%-8s %3d %7s %s\n",
p->driver_name ? p->driver_name : "",
p->name, p->major, range, type);
if (len+begin > off+count)
break;
if (len+begin < off) {
begin += len;
len = 0;
}
}
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
}
/*
* This is the handler for /proc/tty/ldiscs
*/
static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
int count, void *data)
{
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < NR_LDISCS; i++) {
if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED))
continue;
len += sprintf(page+len, "%-10s %2d\n",
ldiscs[i].name ? ldiscs[i].name : "???", i);
if (len+begin > off+count)
break;
if (len+begin < off) {
begin += len;
len = 0;
}
}
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
}
/*
* Thsi function is called by register_tty_driver() to handle
* registering the driver's /proc handler into /proc/tty/driver/<foo>
*/
void proc_tty_register_driver(struct tty_driver *driver)
{
struct proc_dir_entry *ent;
if ((!driver->read_proc && !driver->write_proc) ||
!driver->driver_name ||
driver->proc_entry)
return;
ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver);
if (!ent)
return;
ent->read_proc = driver->read_proc;
ent->write_proc = driver->write_proc;
ent->data = driver;
driver->proc_entry = ent;
}
/*
* This function is called by unregister_tty_driver()
*/
void proc_tty_unregister_driver(struct tty_driver *driver)
{
struct proc_dir_entry *ent;
ent = driver->proc_entry;
if (!ent)
return;
proc_unregister(proc_tty_driver, ent->low_ino);
driver->proc_entry = 0;
kfree(ent);
}
/*
* Called by proc_root_init() to initialize the /proc/tty subtree
*/
void proc_tty_init(void)
{
struct proc_dir_entry *ent;
proc_tty = create_proc_entry("tty", S_IFDIR, &proc_root);
if (!proc_tty)
return;
proc_tty_ldisc = create_proc_entry("ldisc", S_IFDIR, proc_tty);
proc_tty_driver = create_proc_entry("driver", S_IFDIR, proc_tty);
ent = create_proc_entry("ldiscs", 0, proc_tty);
ent->read_proc = tty_ldiscs_read_proc;
ent = create_proc_entry("drivers", 0, proc_tty);
ent->read_proc = tty_drivers_read_proc;
}
...@@ -299,13 +299,41 @@ struct proc_dir_entry proc_openprom = { ...@@ -299,13 +299,41 @@ struct proc_dir_entry proc_openprom = {
extern void openpromfs_init (void); extern void openpromfs_init (void);
#endif /* CONFIG_SUN_OPENPROMFS */ #endif /* CONFIG_SUN_OPENPROMFS */
static int make_inode_number(void)
{
int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
if (i<0 || i>=PROC_NDYNAMIC)
return -1;
set_bit(i, (void *) proc_alloc_map);
return PROC_DYNAMIC_FIRST + i;
}
int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp) int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
{ {
int i;
if (dp->low_ino == 0) {
i = make_inode_number();
if (i < 0)
return -EAGAIN;
dp->low_ino = i;
}
dp->next = dir->subdir; dp->next = dir->subdir;
dp->parent = dir; dp->parent = dir;
dir->subdir = dp; dir->subdir = dp;
if (S_ISDIR(dp->mode)) if (S_ISDIR(dp->mode)) {
if (dp->ops == NULL)
dp->ops = &proc_dir_inode_operations;
dir->nlink++; dir->nlink++;
} else {
if (dp->ops == NULL)
dp->ops = &proc_file_inode_operations;
}
/*
* kludge until we fixup the md device driver
*/
if (dp->low_ino == PROC_MD)
dp->ops = &proc_array_inode_operations;
return 0; return 0;
} }
...@@ -330,28 +358,16 @@ int proc_unregister(struct proc_dir_entry * dir, int ino) ...@@ -330,28 +358,16 @@ int proc_unregister(struct proc_dir_entry * dir, int ino)
return -EINVAL; return -EINVAL;
} }
static int make_inode_number(void)
{
int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
if (i<0 || i>=PROC_NDYNAMIC)
return -1;
set_bit(i, (void *) proc_alloc_map);
return PROC_DYNAMIC_FIRST + i;
}
int proc_register_dynamic(struct proc_dir_entry * dir, int proc_register_dynamic(struct proc_dir_entry * dir,
struct proc_dir_entry * dp) struct proc_dir_entry * dp)
{ {
int i = make_inode_number(); /*
if (i < 0) * Make sure we use a dynamically allocated inode.
return -EAGAIN; * In the future, all procedures should just call
dp->low_ino = i; * proc_register....
dp->next = dir->subdir; */
dp->parent = dir; dp->low_ino = 0;
dir->subdir = dp; return proc_register(dir, dp);
if (S_ISDIR(dp->mode))
dir->nlink++;
return 0;
} }
/* /*
...@@ -404,38 +420,46 @@ static struct inode_operations proc_self_inode_operations = { ...@@ -404,38 +420,46 @@ static struct inode_operations proc_self_inode_operations = {
static struct proc_dir_entry proc_root_loadavg = { static struct proc_dir_entry proc_root_loadavg = {
PROC_LOADAVG, 7, "loadavg", PROC_LOADAVG, 7, "loadavg",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_uptime = { static struct proc_dir_entry proc_root_uptime = {
PROC_UPTIME, 6, "uptime", PROC_UPTIME, 6, "uptime",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_meminfo = { static struct proc_dir_entry proc_root_meminfo = {
PROC_MEMINFO, 7, "meminfo", PROC_MEMINFO, 7, "meminfo",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_kmsg = { static struct proc_dir_entry proc_root_kmsg = {
PROC_KMSG, 4, "kmsg", PROC_KMSG, 4, "kmsg",
S_IFREG | S_IRUSR, 1, 0, 0, S_IFREG | S_IRUSR, 1, 0, 0,
0, &proc_kmsg_inode_operations
}; };
static struct proc_dir_entry proc_root_version = { static struct proc_dir_entry proc_root_version = {
PROC_VERSION, 7, "version", PROC_VERSION, 7, "version",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static struct proc_dir_entry proc_root_pci = { static struct proc_dir_entry proc_root_pci = {
PROC_PCI, 3, "pci", PROC_PCI, 3, "pci",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
#ifdef CONFIG_ZORRO #ifdef CONFIG_ZORRO
static struct proc_dir_entry proc_root_zorro = { static struct proc_dir_entry proc_root_zorro = {
PROC_ZORRO, 5, "zorro", PROC_ZORRO, 5, "zorro",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
static struct proc_dir_entry proc_root_cpuinfo = { static struct proc_dir_entry proc_root_cpuinfo = {
PROC_CPUINFO, 7, "cpuinfo", PROC_CPUINFO, 7, "cpuinfo",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_self = { static struct proc_dir_entry proc_root_self = {
PROC_SELF, 4, "self", PROC_SELF, 4, "self",
...@@ -446,81 +470,99 @@ static struct proc_dir_entry proc_root_self = { ...@@ -446,81 +470,99 @@ static struct proc_dir_entry proc_root_self = {
static struct proc_dir_entry proc_root_malloc = { static struct proc_dir_entry proc_root_malloc = {
PROC_MALLOC, 6, "malloc", PROC_MALLOC, 6, "malloc",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
static struct proc_dir_entry proc_root_kcore = { static struct proc_dir_entry proc_root_kcore = {
PROC_KCORE, 5, "kcore", PROC_KCORE, 5, "kcore",
S_IFREG | S_IRUSR, 1, 0, 0, S_IFREG | S_IRUSR, 1, 0, 0,
0, &proc_kcore_inode_operations
}; };
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
static struct proc_dir_entry proc_root_modules = { static struct proc_dir_entry proc_root_modules = {
PROC_MODULES, 7, "modules", PROC_MODULES, 7, "modules",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_ksyms = { static struct proc_dir_entry proc_root_ksyms = {
PROC_KSYMS, 5, "ksyms", PROC_KSYMS, 5, "ksyms",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
static struct proc_dir_entry proc_root_stat = { static struct proc_dir_entry proc_root_stat = {
PROC_STAT, 4, "stat", PROC_STAT, 4, "stat",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_devices = { static struct proc_dir_entry proc_root_devices = {
PROC_DEVICES, 7, "devices", PROC_DEVICES, 7, "devices",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_interrupts = { static struct proc_dir_entry proc_root_interrupts = {
PROC_INTERRUPTS, 10,"interrupts", PROC_INTERRUPTS, 10,"interrupts",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#ifdef __SMP_PROF__ #ifdef __SMP_PROF__
static struct proc_dir_entry proc_root_smp = { static struct proc_dir_entry proc_root_smp = {
PROC_SMP_PROF, 3,"smp", PROC_SMP_PROF, 3,"smp",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
static struct proc_dir_entry proc_root_filesystems = { static struct proc_dir_entry proc_root_filesystems = {
PROC_FILESYSTEMS, 11,"filesystems", PROC_FILESYSTEMS, 11,"filesystems",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_dma = { static struct proc_dir_entry proc_root_dma = {
PROC_DMA, 3, "dma", PROC_DMA, 3, "dma",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_ioports = { static struct proc_dir_entry proc_root_ioports = {
PROC_IOPORTS, 7, "ioports", PROC_IOPORTS, 7, "ioports",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_cmdline = { static struct proc_dir_entry proc_root_cmdline = {
PROC_CMDLINE, 7, "cmdline", PROC_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#ifdef CONFIG_RTC #ifdef CONFIG_RTC
static struct proc_dir_entry proc_root_rtc = { static struct proc_dir_entry proc_root_rtc = {
PROC_RTC, 3, "rtc", PROC_RTC, 3, "rtc",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
#endif #endif
static struct proc_dir_entry proc_root_locks = { static struct proc_dir_entry proc_root_locks = {
PROC_LOCKS, 5, "locks", PROC_LOCKS, 5, "locks",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_mounts = { static struct proc_dir_entry proc_root_mounts = {
PROC_MTAB, 6, "mounts", PROC_MTAB, 6, "mounts",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_swaps = { static struct proc_dir_entry proc_root_swaps = {
PROC_SWAP, 5, "swaps", PROC_SWAP, 5, "swaps",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
static struct proc_dir_entry proc_root_profile = { static struct proc_dir_entry proc_root_profile = {
PROC_PROFILE, 7, "profile", PROC_PROFILE, 7, "profile",
S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0, S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
0, &proc_profile_inode_operations
}; };
static struct proc_dir_entry proc_root_slab = { static struct proc_dir_entry proc_root_slab = {
PROC_SLABINFO, 8, "slabinfo", PROC_SLABINFO, 8, "slabinfo",
S_IFREG | S_IRUGO, 1, 0, 0, S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
}; };
void proc_root_init(void) void proc_root_init(void)
...@@ -555,6 +597,7 @@ void proc_root_init(void) ...@@ -555,6 +597,7 @@ void proc_root_init(void)
proc_register(&proc_root, &proc_root_malloc); proc_register(&proc_root, &proc_root_malloc);
#endif #endif
proc_register(&proc_root, &proc_root_kcore); proc_register(&proc_root, &proc_root_kcore);
proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
proc_register(&proc_root, &proc_root_modules); proc_register(&proc_root, &proc_root_modules);
...@@ -589,7 +632,10 @@ void proc_root_init(void) ...@@ -589,7 +632,10 @@ void proc_root_init(void)
if (prof_shift) { if (prof_shift) {
proc_register(&proc_root, &proc_root_profile); proc_register(&proc_root, &proc_root_profile);
proc_root_profile.size = (1+prof_len) * sizeof(unsigned long);
} }
proc_tty_init();
} }
...@@ -666,8 +712,17 @@ static int proc_root_lookup(struct inode * dir,const char * name, int len, ...@@ -666,8 +712,17 @@ static int proc_root_lookup(struct inode * dir,const char * name, int len,
{ {
unsigned int pid, c; unsigned int pid, c;
int i, ino, retval; int i, ino, retval;
struct task_struct *p;
dir->i_count++; dir->i_count++;
if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
dir->i_nlink = proc_root.nlink;
for_each_task(p)
if (p && p->pid)
dir->i_nlink++;
}
retval = proc_lookup(dir, name, len, result); retval = proc_lookup(dir, name, len, result);
if (retval != -ENOENT) { if (retval != -ENOENT) {
iput(dir); iput(dir);
......
...@@ -53,7 +53,7 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int ...@@ -53,7 +53,7 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int
* this is a new version of the above that records errors it finds in *errp, * this is a new version of the above that records errors it finds in *errp,
* but continues and zeros the rest of the buffer. * but continues and zeros the rest of the buffer.
*/ */
unsigned int csum_partial_copy_from_user(int *errp, char *src, char *dst, int len, unsigned int sum); unsigned int csum_partial_copy_from_user(char *src, char *dst, int len, unsigned int sum, int *errp);
/* /*
* this routine is used for miscellaneous IP-like checksums, mainly * this routine is used for miscellaneous IP-like checksums, mainly
......
...@@ -122,6 +122,7 @@ struct termios { ...@@ -122,6 +122,7 @@ struct termios {
#define B230400 0010003 #define B230400 0010003
#define B460800 0010004 #define B460800 0010004
#define CIBAUD 002003600000 /* input baud rate (not used) */ #define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */ #define CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */ /* c_lflag bits */
......
...@@ -33,6 +33,8 @@ struct termio { ...@@ -33,6 +33,8 @@ struct termio {
#define TIOCM_DSR 0x100 #define TIOCM_DSR 0x100
#define TIOCM_CD TIOCM_CAR #define TIOCM_CD TIOCM_CAR
#define TIOCM_RI TIOCM_RNG #define TIOCM_RI TIOCM_RNG
#define TIOCM_OUT1 0x2000
#define TIOCM_OUT2 0x4000
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
......
...@@ -223,6 +223,10 @@ struct proc_dir_entry { ...@@ -223,6 +223,10 @@ struct proc_dir_entry {
void (*fill_inode)(struct inode *); void (*fill_inode)(struct inode *);
struct proc_dir_entry *next, *parent, *subdir; struct proc_dir_entry *next, *parent, *subdir;
void *data; void *data;
int (*read_proc)(char *page, char **start, off_t off,
int count, void *data);
int (*write_proc)(struct file *file, const char *buffer,
unsigned long count, void *data);
}; };
extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start, extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
...@@ -327,6 +331,7 @@ extern int proc_openprom_regdev(struct openpromfs_dev *); ...@@ -327,6 +331,7 @@ extern int proc_openprom_regdev(struct openpromfs_dev *);
extern int proc_openprom_unregdev(struct openpromfs_dev *); extern int proc_openprom_unregdev(struct openpromfs_dev *);
extern struct inode_operations proc_dir_inode_operations; extern struct inode_operations proc_dir_inode_operations;
extern struct inode_operations proc_file_inode_operations;
extern struct inode_operations proc_net_inode_operations; extern struct inode_operations proc_net_inode_operations;
extern struct inode_operations proc_netdir_inode_operations; extern struct inode_operations proc_netdir_inode_operations;
extern struct inode_operations proc_scsi_inode_operations; extern struct inode_operations proc_scsi_inode_operations;
...@@ -344,3 +349,16 @@ extern struct inode_operations proc_fd_inode_operations; ...@@ -344,3 +349,16 @@ extern struct inode_operations proc_fd_inode_operations;
extern struct inode_operations proc_ringbuf_inode_operations; extern struct inode_operations proc_ringbuf_inode_operations;
#endif #endif
#endif #endif
/*
* generic.c
*/
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent);
/*
* proc_tty.c
*/
extern void proc_tty_init(void);
extern void proc_tty_register_driver(struct tty_driver *driver);
extern void proc_tty_unregister_driver(struct tty_driver *driver);
...@@ -123,7 +123,10 @@ struct serial_multiport_struct { ...@@ -123,7 +123,10 @@ struct serial_multiport_struct {
*/ */
struct serial_icounter_struct { struct serial_icounter_struct {
int cts, dsr, rng, dcd; int cts, dsr, rng, dcd;
int reserved[16]; int rx, tx;
int frame, overrun, parity, brk;
int buf_overrun;
int reserved[9];
}; };
...@@ -144,7 +147,9 @@ struct serial_icounter_struct { ...@@ -144,7 +147,9 @@ struct serial_icounter_struct {
* Counters of the input lines (CTS, DSR, RI, CD) interrupts * Counters of the input lines (CTS, DSR, RI, CD) interrupts
*/ */
struct async_icount { struct async_icount {
__u32 cts, dsr, rng, dcd; __u32 cts, dsr, rng, dcd, tx, rx;
__u32 frame, parity, overrun, brk;
__u32 buf_overrun;
}; };
struct serial_state { struct serial_state {
...@@ -178,6 +183,7 @@ struct async_struct { ...@@ -178,6 +183,7 @@ struct async_struct {
int read_status_mask; int read_status_mask;
int ignore_status_mask; int ignore_status_mask;
int timeout; int timeout;
int quot;
int x_char; /* xon/xoff character */ int x_char; /* xon/xoff character */
int close_delay; int close_delay;
unsigned short closing_wait; unsigned short closing_wait;
...@@ -235,5 +241,6 @@ struct rs_multiport_struct { ...@@ -235,5 +241,6 @@ struct rs_multiport_struct {
/* Export to allow PCMCIA to use this - Dave Hinds */ /* Export to allow PCMCIA to use this - Dave Hinds */
extern int register_serial(struct serial_struct *req); extern int register_serial(struct serial_struct *req);
extern void unregister_serial(int line); extern void unregister_serial(int line);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_SERIAL_H */ #endif /* _LINUX_SERIAL_H */
...@@ -328,13 +328,8 @@ extern struct tty_ldisc tty_ldisc_N_TTY; ...@@ -328,13 +328,8 @@ extern struct tty_ldisc tty_ldisc_N_TTY;
extern int n_tty_ioctl(struct tty_struct * tty, struct file * file, extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
/* serial.c */ /* pcxx.c */
extern int rs_open(struct tty_struct * tty, struct file * filp);
/* pty.c */
extern int pty_open(struct tty_struct * tty, struct file * filp);
extern int pcxe_open(struct tty_struct *tty, struct file *filp); extern int pcxe_open(struct tty_struct *tty, struct file *filp);
/* console.c */ /* console.c */
......
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
struct tty_driver { struct tty_driver {
int magic; /* magic number for this structure */ int magic; /* magic number for this structure */
const char *driver_name;
const char *name; const char *name;
int name_base; /* offset of printed name */ int name_base; /* offset of printed name */
short major; /* major device number */ short major; /* major device number */
...@@ -117,6 +118,7 @@ struct tty_driver { ...@@ -117,6 +118,7 @@ struct tty_driver {
struct termios init_termios; /* Initial termios */ struct termios init_termios; /* Initial termios */
int flags; /* tty driver flags */ int flags; /* tty driver flags */
int *refcount; /* for loadable tty drivers */ int *refcount; /* for loadable tty drivers */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
struct tty_driver *other; /* only used for the PTY driver */ struct tty_driver *other; /* only used for the PTY driver */
/* /*
...@@ -150,6 +152,10 @@ struct tty_driver { ...@@ -150,6 +152,10 @@ struct tty_driver {
void (*set_ldisc)(struct tty_struct *tty); void (*set_ldisc)(struct tty_struct *tty);
void (*wait_until_sent)(struct tty_struct *tty, int timeout); void (*wait_until_sent)(struct tty_struct *tty, int timeout);
void (*send_xchar)(struct tty_struct *tty, char ch); void (*send_xchar)(struct tty_struct *tty, char ch);
int (*read_proc)(char *page, char **start, off_t off,
int count, void *data);
int (*write_proc)(struct file *file, const char *buffer,
unsigned long count, void *data);
/* /*
* linked list pointers * linked list pointers
...@@ -197,4 +203,8 @@ struct tty_driver { ...@@ -197,4 +203,8 @@ struct tty_driver {
#define PTY_TYPE_MASTER 0x0001 #define PTY_TYPE_MASTER 0x0001
#define PTY_TYPE_SLAVE 0x0002 #define PTY_TYPE_SLAVE 0x0002
/* serial subtype definitions */
#define SERIAL_TYPE_NORMAL 1
#define SERIAL_TYPE_CALLOUT 2
#endif /* #ifdef _LINUX_TTY_DRIVER_H */ #endif /* #ifdef _LINUX_TTY_DRIVER_H */
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
struct tty_ldisc { struct tty_ldisc {
int magic; int magic;
char *name;
int num; int num;
int flags; int flags;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment