1 *_Design Specification of SAB8253X ASLX Driver for Linux_*
6 The effort to design and implement the ASLX SAB8253X Driver for Aurora
7 <http://www.auroratech.com/> hardware with the functionality described
8 in *_Functional Specification of SAB8253X ASLX Driver for Linux
9 <http://www.telfordtools.com/sab8253x/sab8253xfs.html>_* requires
10 solutions to seven separate problems:
14 1. creating a development environment for maintaining and extending
16 2. integrating the driver into the kernel sources,
17 3. creating a file structure of the driver that aids understanding,
18 4. crafting a reasonable and easy to use user interface,
19 5. developing simple tools and example programs for the driver, and
20 6. designing the driver data structures and
21 7. designing the driver program logic.
26 _Development Environment_
31 There are several possible approaches to creating a development
32 environment. The development environments for many drivers seem
33 to have consisted simply of a single machine, and the developer
34 used only /printk()/ in the driver code to debug. I used such an
35 environment to develop a driver for an IOP480 based intelligent
40 For a driver that provides the functionality described in the Functional
41 Specification, a more sophisticated development and debugging
42 environment is useful. (One could even occasionally wish for an ICE,
43 but that level of resources was not available to me.)
47 The development environment consisted of two 686 class machines, on
48 which the Linux operating system was installed. One machine ran at 800
49 Mhz, the other at 1Ghz. It probably would have been worthwhile to have
50 dual processor machine, and one was added to the development environment
51 later. The 800 Mhz machine hosted the remote gdb application. It ran
52 Redhat Linux 7.0, but because the machine served only as an NFS and
53 remote gdb host, the details of the Linux distribution on this machine
54 are not particularly important.
58 The target machine on which the driver was developed and debugged hosted
59 Suse Linux 7.1 and was later upgraded to Suse Linux 7.3. Suse Linux
60 seemed to provide the most complete Linux distribution with the least
61 hassle in installation. (As the Suse distribution comes on 7 standard
62 CDs or 1 DVD, there is a lot of value in having a DVD drive in the
63 target machine [and the gdb host if it runs a Suse distribution].)
67 The target and remote gdb machines are connected by a 100 Mbps Ethernet
68 network and by a serial crossover cable between the Com1 (ttyS0) ports.
72 When I started developing the driver, I obtained the Linux 2.4.3 sources
73 from The Linux Kernel Archives <http://www.kernel.org/>. Later as later
74 distributions became stable, I switched to the Linux 2.4.6
75 distribution. The sources were installed first in
76 /home/martillo/kernel/linux-2.4.3 and then in
77 /home/martillo/kernel/linux-2.4.6 on the remote gdb host machine, which
82 The sources were imported into CVS on frolix, and the core directory
83 into CVS was added manually because the cvs import function ignores
84 it. I consider it safer to maintain the CVS repository on the remote
85 gdb host machine instead of the target machine because the target
86 machine is likely to crash frequently, and its file system may be put
91 I executed the following commands on the remote gdb host machine.
95 *ln ^Ös /home/martillo/kernel/linux-2.4.3/include/asm-i386
96 /home/martillo/kernel/linux-2.4.3/include/asm*
104 *ln ^Ös /home/martillo/kernel/linux-2.4.6/include/asm-i386
105 /home/martillo/kernel/linux-2.4.6/include/asm*
113 I edited the /etc/exports file to contain the following.
127 Ylith is the original 1 Ghz target machine. Fireball is a 400 Mhz
128 compact PCI target machine. Indefatigable is a dual 1 Ghz target
129 machine. Bohun is a Solaris target machine used for another project.
133 On the frolix, I started NFS with the following commands (contained in a
138 */etc/rc.d/init.d/nfs start*
144 If it had been a Suse Linux machine, I would have used the yast2 control
145 center to start NFS service.
149 On ylith, I created an empty directory /frolix and executed the
154 *mount frolix:/ /frolix*
158 At this point both the remote gdb host (frolix) and the target
159 development and debugging machine can refer to the same files by the
160 same paths. I could have guaranteed the same paths to the source files
161 on both machines if I had simply used /home/martillo as my home
162 directory on frolix and exported /home from frolix to all the other
163 machines so that there would only be one /home directory for all the
164 machines in my network. I was lazy about the network configuration.
168 After making sure that the user martillo had read write access
169 permissions to all the kernel sources, I built the kernel on the target
170 machine from within xemacs with the following sequence of commands.
184 *cd /frolix/home/martillo/kernel/linux-2.4.3*
192 *cd /frolix/home/martillo/kernel/linux-2.4.6*
196 Then make sure that linux-2.4.x/include/asm-i386 is symbolically linked to
197 linux-2.4.x/include/asm.
201 Execute the following emacs command.
210 This command prompts for targets.
214 In the development environment the most useful target string was usually
215 /clean xconfig dep bzImage modules./ The target /xconfig /brings up a
216 configuration window. In the basic development environment, it was
217 generally worthwhile to add SCSI CD ROM, SCSI legacy support, an
218 Ethernet driver and DOS file system support
222 The target/ dep/ creates the dependencies (note that if the kernel tree
223 is ever removed, the .depend and .hdepend files must be regenerated).
224 The /bzImage /target builds the kernel. The /modules/ target generates
225 all the modules to be dynamically installed in the kernel via the
230 After building the kernel, installing the modules in the /lib tree
231 requires the execution (as root) of
239 The command *make install* *INSTALL_PATH=/boot* will install the
240 compressed kernel image as vmlinuz along with other files in the /boot
241 partition. I preferred to use a shell script with commands like the
246 cp /frolix/home/martillo/kernel/linux-2.4.6/arch/i386/boot/bzImage
249 cp /frolix/home/martillo/kernel/linux-2.4.6/System.map
250 /boot/System.map-2.4.6
252 cp /frolix/home/martillo/kernel/linux-2.4.6/.config /boot/vmlinuz_246.config
254 cp /frolix/home/martillo/kernel/linux-2.4.6/include/linux/autoconf.h
255 /boot/vmlinuz_246.autoconf.h
257 cp /frolix/home/martillo/kernel/linux-2.4.6/include/linux/version.h
258 /boot/vmlinuz_246.version.h
262 When the kernel comes from a linux-2.4.3 tree, the obvious substitutions
263 of 3 for 6 are required.
267 Once all the modules and the kernel image are installed, the next step
268 in giving the system the ability to boot with the new linux-2.4.3 or
269 linux-2.4.6 kernel image is the modification of the lilo.conf file.
273 I added the following directives to the lilo.conf file.
277 image = /boot/vmlinuz_243
287 image = /boot/vmlinuz_246
297 In this case /dev/hde7 corresponds to the /boot partition, and the
298 options linux_2.4.3 and linux_2.4.6 will be added to the boot menu once
299 the *lilo* command has been executed. In other system setups the disk
300 partition that corresponds to /boot might have a different name like
305 Once the new kernel successfully boots, the next step to creating a
306 driver development and debugging environment is patching the kernel for
307 remote gdb debugging.
311 The necessary patch can be obtained from kgdb: Source level debugging of
312 linux kernel <http://kgdb.sourceforge.net/downloads.html>.
316 Now the kernel can be built again with the extra step of configuring for
317 remote gdb support in the kernel configuration menu.
321 The following directives should be added to lilo.conf.
325 image = /boot/vmlinuz_243
329 append = "gdb gdbttyS=0 gdbbaud=115200"
337 image = /boot/vmlinuz_246
341 append = "gdb gdbttyS=0 gdbbaud=115200"
350 Then lilo can be executed. On reboot the boot menu will include
351 options for debug243 and debug246.
355 To test the patch, select one of the debug options. Then, on the remote
356 gdb host machine execute the following command.
360 stty 115200 < /dev/ttyS0
364 Start up an *xemacs* process. Execute the following commands within
374 Then within the shell window execute the following command.
378 cd /frolix/home/martillo/kernel/linux-2.4./X/
382 Then invoke the remote debugger.
391 Reply to the file prompt with *vmlinux.*
395 In the gdb window, execute the following command.
399 target remote /dev/ttyS0
403 The gdb window should break in gdbstub.c which will be displayed in the
408 At this point, all the basic gdb remote debugging capabilities are ready
413 To access the hardware breakpoint capability of the i386 processor, the
414 following commands can be loaded directly or from a file with the
419 #Hardware breakpoints in gdb
423 #Using ia-32 hardware breakpoints.
427 #4 hardware breakpoints are available in ia-32 processors. These breakpoints
429 #do not need code modification. They are set using debug registers.
433 #Each hardware breakpoint can be of one of the
435 #three types: execution, write, access.
437 #1. An Execution breakpoint is triggered when code at the breakpoint
442 #2. A write breakpoint ( aka watchpoints ) is triggered when memory location
444 #at the breakpoint address is written.
446 #3. An access breakpoint is triggered when memory location at the breakpoint
448 #address is either read or written.
452 #As hardware breakpoints are available in limited number, use software
454 #breakpoints ( br command in gdb ) instead of execution hardware
459 #Length of an access or a write breakpoint defines length of the datatype to
461 #be watched. Length is 1 for char, 2 short , 3 int.
465 #For placing execution, write and access breakpoints, use commands
467 #hwebrk, hwwbrk, hwabrk
469 #To remove a breakpoint use hwrmbrk command.
473 #These commands take following types of arguments. For arguments associated
475 #with each command, use help command.
477 #1. breakpointno: 0 to 3
481 #3. address: Memory location in hex ( without 0x ) e.g c015e9bc
485 #Use the command exinfo to find which hardware breakpoint occured.
491 #hwebrk breakpointno address
495 maintenance packet Y$arg0,0,0,$arg1
501 hwebrk breakpointno address
503 Places a hardware execution breakpoint
509 #hwwbrk breakpointno length address
513 maintenance packet Y$arg0,1,$arg1,$arg2
519 hwwbrk breakpointno length address
521 Places a hardware write breakpoint
527 #hwabrk breakpointno length address
531 maintenance packet Y$arg0,1,$arg1,$arg2
537 hwabrk breakpointno length address
539 Places a hardware access breakpoint
545 #hwrmbrk breakpointno
549 maintenance packet y$arg0
557 Removes a hardware breakpoint
567 maintenance packet qE
575 Gives information about a breakpoint.
581 Once the above macros are define, the developer can set hardware
586 The next step to creating a useful development and debugging environment
587 is to provide a shell script to for remote debugging of dynamically
588 loaded modules. The following shell script (called *loadmodule.sh*)
589 creates a gdb script called *load/ModuleName/* in
590 /frolix/home/martillo/kernel/linux-2.4.6 when it is invoked (as root)
591 with the following command.
593 loadmodule.sh modulename
597 In order to decrease the probability of confusion, I usually make a link
598 in kernel root directory, /frolix/home/martillo/kernel/linux-2.4.6, to
599 the location of the module to be debugged in the kernel tree. The above
600 command is invoked on the target machine (ylith) in the root directory.
601 On the remote debug machine, in the gdb command window, whose working
602 directory should be the kernel root directory,
603 /frolix/home/martillo/kernel/linux-2.4.6, the command, *script
604 load/ModuleName/*, is invoked. Once the script is executed the symbols
605 for the module are available for remote symbolic debugging.
611 # This script loads a module on a target machine and generates a gdb script.
613 # source generated gdb script to load the module file at appropriate
622 # Loading the module on target machine and generating gdb script)
624 # [foo]$ loadmodule.sh <modulename>
628 # Loading the module file into gdb
630 # (gdb) source <gdbscriptpath>
634 # Modify following variables according to your setup.
636 # TESTMACHINE - Name of the target machine
638 # GDBSCRIPTS - The directory where a gdb script will be generated
642 # Author: Amit S. Kale (akale@veritas.com).
646 # If you run into problems, please check files pointed to by following
650 # ERRFILE - /tmp/<modulename>.errs contains stderr output of insmod
652 # MAPFILE - /tmp/<modulename>.map contains stdout output of insmod
654 # GDBSCRIPT - $GDBSCRIPTS/load<modulename> gdb script.
660 GDBSCRIPTS=/frolix/home/martillo/kernel/linux-2.4.6
664 if [ $# -lt 1 ] ; then {
666 echo Usage: $0 modulefile
676 MODULEFILEBASENAME=`basename $1`
680 if [ $MODULEFILE = $MODULEFILEBASENAME ] ; then {
682 MODULEFILE=`pwd`/$MODULEFILE
688 ERRFILE=/tmp/$MODULEFILEBASENAME.errs
690 MAPFILE=/tmp/$MODULEFILEBASENAME.map
692 GDBSCRIPT=$GDBSCRIPTS/load$MODULEFILEBASENAME
696 function findaddr() {
698 local ADDR=0x$(echo "$SEGMENTS" | \
700 grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \
702 sed 's/[ ]*[^ ]*$//')
710 function checkerrs() {
712 if [ "`cat $ERRFILE`" != "" ] ; then {
724 #echo Copying $MODULEFILE to $TESTMACHINE
726 #*rcp $MODULEFILE root@${TESTMACHINE}:
730 echo Loading module $MODULEFILE
732 #rsh -l root $TESTMACHINE /sbin/insmod -m ./`basename $MODULEFILE` \
734 # > $MAPFILE 2> $ERRFILE &
736 /sbin/insmod -m ./`basename $MODULEFILE` $2 . . > $MAPFILE 2> $ERRFILE &
744 NUMLINES=`grep -n '^$' $MAPFILE | sed -e 's/:.*//g'`
746 SEGMENTS=`head -n $NUMLINES $MAPFILE | tail -n $(eval expr $NUMLINES - 1)`
748 TEXTADDR=$(findaddr "\\.text[^.]")
750 LOADSTRING="add-symbol-file $MODULEFILE $TEXTADDR"
752 SEGADDRS=`echo "$SEGMENTS" | awk '//{
754 if ($1 != ".text" && $1 != ".this" &&
756 $1 != ".kstrtab" && $1 != ".kmodtab") {
758 print " -s " $1 " 0x" $3 " "
764 LOADSTRING="$LOADSTRING $SEGADDRS"
766 echo Generating script $GDBSCRIPT
768 echo $LOADSTRING > $GDBSCRIPT
772 With the addition of the above shell script, the driver development and
773 debugging environment is almost complete. Other useful tools for
774 developing and debugging this type of serial driver would include a
775 Wanalyzer (I used an Interview 7700 and an HP 4952A in developing this
776 driver), a breakout box that displays interface signal states and (for
777 developing the serial Ethernet-like network driver) several WAN LAN VLAN
778 routers as described in *Packet Switching Software and Platforms
779 <http://members.aol.com/Telford001/vrouter2g.html>*, *Routing in a
780 Bridged Network <http://members.aol.com/Telford001/routetti2.html>, **A
781 WAN SUBSYSTEM for a High Performance Packet Switch
782 <http://members.aol.com/Keleustes/syncdob.html>* and *A New High
783 Performance Architecture for Routers, Bridges and LAN Switches (Software
784 Defined Internetworking)
785 <http://members.aol.com/Ishtar7713/private/sdi4.html>.*
790 _Integration into the Kernel Sources_
795 The driver has its own directory, {kernel root
796 directory}/drivers/net/wan/8253x, in the 2.4.* kernel source tree.
800 To facilitate the automatic build of the 8253x driver, the following
801 standard kernel files were modified.
805 1. {kernel root directory}/drivers/net/wan/Config.in to
810 tristate ' Aurora Technology, Inc. synchronous asynchronous PCI cards
818 2. {kernel root directory}/drivers/net/wan/Makefile to
819 which the following lines were added,
823 subdir-$(CONFIG_ATI_XX20) += 8253x
827 ifeq ($(CONFIG_ATI_XX20),y)
829 obj-y += 8253x/ASLX.o
835 When the driver is built as a dynamically loaded module, the following
836 macro commands in the file 8253xini.c puts the module entry points in
837 the special module entry point segment.
841 module_init(auraXX20_probe);
843 module_exit(auraXX20_cleanup);
847 The sources are provided to the users in a patch file, tentatively named
848 8253x.patch <http://www.telfordtools.com/sab8253x/8253x.patch>.
852 To install it the user sets his directory to the top level of the kernel
853 sources and executes the following command.
857 patch ^Öp1 < /{directory-patch}//8253x.patch
863 _File Structure of the ASLX Driver Source Code_
867 The following files are present in the driver directory.
929 The source code is divided functionally among the files of the ASLX driver.
933 8253xcfg.c is the source for a user application that configures 8253x
934 control registers to provide clocking. 8253xmac.c is the source for a
935 user application that sets a pseudo-MAC address for the network driver.
939 8253xini.c contains the initialization/probe logic.
943 8253xint.c contains the common interrupt logic.
947 8253xtty.c contains the asynchronous TTY logic.
951 8253xsyn.c contains the synchronous TTY logic.
955 8253xnet.c contains the network driver logic.
959 8253xchr.c contains the character driver logic.
964 8253xdbg.c contains some debugging functions.
968 8253xutl.c contains most of the functions that are common among the
969 different driver functional subunits.
973 8253xplx.c contains some functions specific to the PLX9050 (a PCI bridge
974 chip) and specifically to reading and reprogramming the associated
979 amcc5920.c contains some functions specific to the AMCC5920 (a PCI
980 bridge chip) and specifically to reading and reprogramming the
981 associated serial EEPROM.
985 8253xmcs.c contains functions specific to programming the multichannel
986 server (mostly G-LINK related logic, programming the sp502 driver chip
987 and reading or programming the serial EEPROM associated with the
988 interface cards contained within the MCS unit).
992 crc32.c contains logic to append a CRC32 to a pseudo MAC frame that is
993 generated by the network driver.
997 8253x.h contains symbols, structures and macros that relate mostly to
998 the 8253x chips and ports.
1002 8253xctl.h contains symbols, structures and macros that relate mostly to
1007 8253xmcs.h contains symbols and structures that relate mostly to the
1008 multichannel server. A lot of this file relates to G-LINK.
1012 sp502.h contains symbols and structures that relate to the programming
1013 of the hardware interface line drivers of the 3500 adapter cards of the
1014 multichannel server.
1018 8253xioc.h contains symbols and structures that relate to private ioctls.
1022 PciRegs.h contains symbols and structures that relate to PCI
1023 configuration space.
1027 Reg9050.h contains symbols and structures that relate to the PLX9050 PCI
1028 interface chip and its serial eprom
1032 crc32.h, crc32dcl.h and .endian.h contain symbols, structures and macros
1033 that relate to generating a correct CRC32.
1037 ring.h contains symbols and structures that relate to the network driver
1038 frame transmission ring and frame reception.
1042 The Makefile is a standard Linux kernel Makefile whose structure is
1043 dictated by the current Linux build formalism.
1048 _Using the ASLX Driver _
1054 The ASLX driver is designed to be a ^Óplug-and-play^Ô driver as far as
1055 possible. If it is built as a dynamically loadable module, the user
1056 (or relevant system configuration file) invokes /insmod /to load the
1061 The following parameters can be set on the /insmod/ command line.
1065 MODULE_PARM(xx20_minorstart, "i");/*when statically linked autodected
1066 otherwise 128 by default*/
1068 MODULE_PARM(sab8253xc_major, "i");/*major dev for character device, by
1071 MODULE_PARM(auraXX20n_debug, "i");/*turns on debugging messages, default
1074 MODULE_PARM(auraXX20n_name, "s"); /*base network driver name = 8253x000*/
1076 MODULE_PARM(sab8253xn_listsize, "i"); /*transmit ring size default 32*/
1078 MODULE_PARM(sab8253xc_name, "s");/*registered name for char driver =
1081 MODULE_PARM(sab8253x_default_sp502_mode, "i");
1086 The asynchronous TTY functionality can immediately be used without
1087 extra configuration. [Note that immediate use of the WMS3500 products
1088 is possible because the default value of sab8253x_default_sp502_mode
1089 is SP502_RS232_MODE (== 1). If a different default mode is needed, it
1090 can be set as options in the /etc/modules.conf file. OFF = 0.
1092 RS232 = 1, RS422 = 2, RS485 = 3, RS449 = 4, EIA530 = 5 and V.35 = 6, as
1093 defined in 8253xioc.h.]
1097 The MAKETERMS script below parses the /proc/tty/driver/auraserial file
1098 to make the asynchronous TTY device files in the /dev directory.
1104 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1105 '/[a-zA-Z]/d' | sed -e 's/://'`
1113 TTYNAME=/dev/ttyS${TTYDEV}
1115 mknod $TTYNAME c 4 $i
1117 TTYDEV=$((${TTYDEV}+1))
1123 The MAKEPROTO script below provides a prototype to modify the
1124 /etc/inittab file so that an agetty process can be spawned on every
1125 other /dev/ttyS* at 9600 bps
1131 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1132 '/[a-zA-Z]/d' | sed -e 's/://'`
1144 TTYNAME=ttyS${TTYDEV}
1146 echo ${LEADCHAR}${NAME}:35:respawn:/sbin/agetty 9600 ${TTYNAME}
1148 TTYDEV=$((${TTYDEV}+1))
1150 if [ -z "$LEADCHAR" ]
1167 If loopback cables are connected between successive TTY ports on each
1168 Aurora adapter card or unit, the command
1172 cu ^Öl /dev/ttyS{n} ^Ös 9600
1176 would connect to the login that was spawned on /dev/ttyS{n-1}.
1180 The script MAKESTERMS (viz below) creates synchronous TTY dev files for
1181 all the Aurora serial ports.
1187 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1188 '/[a-zA-Z]/d' | sed -e 's/://'`
1196 TTYNAME=/dev/sttyS${TTYDEV}
1198 mknod $TTYNAME c 5 $i
1200 TTYDEV=$((${TTYDEV}+1))
1206 The MAKESPROTO script below creates a prototype with which to modify the
1207 /etc/inittab file to spawn an agetty process on every other
1208 /dev/sttyS{N} device.
1214 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1215 '/[a-zA-Z]/d' | sed -e 's/://'`
1227 TTYNAME=sttyS${TTYDEV}
1229 echo ${LEADCHAR}${NAME}:35:respawn:/sbin/agetty 9600 ${TTYNAME}
1231 TTYDEV=$((${TTYDEV}+1))
1233 if [ -z "$LEADCHAR" ]
1250 The simplest way to use these terminals with the agetty process that
1251 comes with the Linux distribution is to leave externally clocked (the
1252 default) the terminals on which agetty has been spawned.
1256 The loopback cable can be connected to a port on which agetty is not
1257 being run. The clockside of the cable is connected to this port. The
1258 user can run the MAKECLOCKING script below.
1262 echo 8253xcfg $1 -n 64 158 56 4 192 140 15
1264 8253xcfg $1 -n 64 158 56 4 192 140 15
1268 The numbers on the 8253xcfg command line are new (decimal) values for
1269 the channel control, mode and baud rate registers. The file 8253xioc.h
1270 and sab8253x manuals from Siemens/Infineon can assist in explaining the
1271 reasoning behind these values. The 8253xcfg sets the mode, channel
1272 control and baudrate generator registers of the port specified by
1273 /dev/sttyS{N-1} which is the argument $1 of this script file. 8253xcfg
1274 is a simple example program that is included with the driver sources.
1275 It is described in the next section of this document.
1279 At this point, the user could execute the following command to connect
1280 synchronously to the peer synchronous TTY port.
1284 cu ^Öl /dev/sttyS{n} ^Ös 9600
1288 To turn off internal clocking use the following command.
1292 8253xcfg /dev/sttyS? ^Ön 64 152 0 4 0 140 15
1296 To use an ASLX network device the following commands would be used.
1300 *MAKECLOCKING /dev/sttyS*/{N} [if the interface is to provide clock]/
1302 *stty */{speed} /*< /dev/sttyS*/{N} [if the interface is to provide clock]/
1306 To set the MAC address, which defaults to 00:00:00:00:00:00 and which
1307 consequently must be changed, use the following command.
1311 *ifconfig 8253x*/{mdev} /*hw ether*/ {mac address} [as root]/
1315 [Note that the 8253x{mdev} interface must not be running when the above
1316 command is executed.]
1320 To set the IP address, use the command.
1324 *ifconfig 8253x*/{mdev} {ipadress} [as root]/
1328 [Note that the two ifconfig commands can be combined on one line. If
1329 they are executed separately the MAC address command must be executed
1330 before the IP address command.]
1334 After the completion of the above commands, assuming there is an active
1335 network peer that uses the same serial Ethernet frame structure, it
1336 should be possible to ping or telnet to the peer networking device.
1340 {mdev} is the minor device number (in decimal, 3 digits including
1341 leading 0s required) associated with /dev/sttyS{N}.//
1345 To disable the network interface use the following command.
1349 *ifconfig 8253x*/{mdev} /*down*/ [as root]/
1353 If there is a need to disable clocking on a serial port, the
1354 MAKENONCLOCKING shell script is invoked with the TTY device as an
1355 argument as follows.
1359 MAKENONCLOCKING /dev/ttyS{N}
1363 The shell script contains the following commands.
1367 echo 8253xcfg $1 -n 64 152 0 4 192 140 255
1369 8253xcfg $1 -n 64 152 0 4 192 140 255
1373 The numbers on the 8253xcfg command line are new (decimal) values for
1374 the channel control, mode and baud rate registers. The file 8253xioc.h
1375 and sab8253x manuals from Siemens/Infineon can assist in explaining the
1376 reasoning behind these values. The 8253xcfg sets the mode, channel
1377 control and baudrate generator registers of the port specified by
1378 /dev/sttyS{N-1} which is the argument $1 of this script file. 8253xcfg
1379 is a simple example program that is included with the driver sources.
1380 It is described in the next section of this document.
1386 _Simple Tools and Example Programs_
1390 The tools and example programs supplied with the SAB8253X ASLX driver
1408 This program performs the bit-banging necessary to read and to program
1409 the serial eprom of the PLX9050.
1413 To access the serial eprom on an adapter card the program opens up a TTY
1414 device on the adapter card, whose serial eprom is to be modified.
1415 This TTY device can either be synchronous, asynchronous or callout. The
1416 TTY device is passed as an argument when the program is invoked.
1420 The program uses the ATIS_IOCGSEP9050 IOCTL to get the current serial
1421 eprom values and the ATIS_IOCSSEP9050 IOCTL to set the new serial eprom
1426 Here is the source code of the program.
1432 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1436 * This program is free software; you can redistribute it and/or
1438 * modify it under the terms of the GNU General Public License
1440 * as published by the Free Software Foundation; either version
1442 * 2 of the License, or (at your option) any later version.
1450 #include <sys/types.h>
1452 #include <sys/stat.h>
1460 #include "8253xioc.h"
1462 #include "Reg9050.h"
1468 /* This application shows how to load the */
1470 /* channel control, mode and rx frame
1473 /* check registers via an ioctl.*/
1477 int main(int argc, char **argv)
1483 unsigned short oldeeprom[EPROM9050_SIZE], neweeprom[EPROM9050_SIZE];
1491 unsigned short *pointer;
1493 unsigned short *pointerold;
1505 fprintf(stderr, "Syntax: %s {portname} [-n] {prom values}.\n", *argv);
1511 fd = open(argv[1], O_RDWR);
1517 perror("open failed.");
1525 if((argc > 2) && !strcmp("-n", argv[2]))
1535 /* get the current values */
1537 if(ioctl(fd, ATIS_IOCGSEP9050, &oldeeprom) < 0)
1541 perror("ioctl failed.");
1547 /* set up the existing values as defaults */
1549 memcpy(neweeprom, oldeeprom, sizeof(oldeeprom));
1551 /* gather all new values from the
1554 /* or via tty input.*/
1556 for(count = (2+noprompt), pointer = neweeprom; count < argc; ++count,
1561 *pointer = atoi(argv[count]);
1565 pointer = neweeprom;
1567 pointerold = oldeeprom;
1569 for(epromindex = 0; epromindex < EPROM9050_SIZE; ++epromindex)
1573 fprintf(stderr, "LOCATION %i [%4.4x/%4.4x]: ", epromindex,
1574 *pointerold, *pointer);
1582 if(count = read(0, buffer, 150), count <= 0)
1590 buffer[count] = '\0';
1592 if(buffer[0] != '\n')
1596 sscanf(buffer, "%x", &value);
1598 *pointer = (unsigned short) value;
1608 fprintf(stderr, "\n");
1618 /* This ioctl does the actual register
1621 if(ioctl(fd, ATIS_IOCSSEP9050, neweeprom) < 0)
1625 perror("ioctl failed.");
1639 With the above program it is possible to change PCI vendor and device ID
1640 values of the adapter card. At that point the card would no longer be
1641 visible to the driver. To correct the vendor and device IDs use the
1642 *lspci* Linux command to find out what new values are and recompile the
1643 driver code after modifying the symbols that correspond to the correct
1644 vendor and device Ids of the card to the new values. (I should make the
1645 vendor and device IDs module parameters that can be set from the
1646 *insmod* command line.) The eprom9050 can be invoked to write the
1647 device and vendor IDs to the correct values. Of course, then the card
1648 will no longer be visible to the new version of the driver, and the
1649 original version of the driver must be used to communicate with this card.
1658 The 8253xcfg command provides access to images of the channel control,
1659 mode and baud rate generator registers of the serial port that is
1660 specified by the minor device number (port number = minor device number
1661 ^Ö minor_start) of the TTY device (either synchronous, asynchronous or
1662 callout) specified on the command line by which 8253xcfg is invoked.
1663 The next time the port is initialized (usually on the first open after
1664 every process that currently has the port open has closed it) these
1665 registers are set with the values of their images. The 8253xcfg command
1666 can make a synchronous port clocking or non-clocking. Note that even
1667 though 8253xcfg operates on a TTY device, the open that finally sets the
1668 registers with the values from the images can be either a synchronous
1669 TTY, a network device or a synchronous character device open. The
1670 program uses the ATIS_IOCGPARAMS IOCTL to get the current values of the
1671 images of the registers and employs the ATIS_IOCSPARAMS IOCTL to set the
1672 current values of the images of the registers. Here is the source of
1673 the 8253xcfg program.
1679 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1683 * This program is free software; you can redistribute it and/or
1685 * modify it under the terms of the GNU General Public License
1687 * as published by the Free Software Foundation; either version
1689 * 2 of the License, or (at your option) any later version.
1697 #include <sys/types.h>
1699 #include <sys/stat.h>
1707 #include "8253xioc.h"
1735 /* This application shows how to load the */
1737 /* channel control, mode and rx frame
1740 /* check registers via an ioctl.*/
1744 int main(int argc, char **argv)
1750 struct channelcontrol ccontrolold, ccontrolnew;
1758 unsigned char *pointer;
1760 unsigned char *pointerold;
1762 char **promptpointer = prompts;
1772 fprintf(stderr, "Syntax: %s {portname} [-n] [ccr0 [ccr1 [ccr2
1773 [ccr3 [ccr4 [mode [rlcr]]]]]]].\n", *argv);
1779 fd = open(argv[1], O_RDWR);
1785 perror("open failed.");
1793 if((argc > 2) && !strcmp("-n", argv[2]))
1803 /* get the current values */
1805 if(ioctl(fd, ATIS_IOCGPARAMS, &ccontrolold) < 0)
1809 perror("ioctl failed.");
1815 /* set up the existing values as defaults */
1817 ccontrolnew = ccontrolold;
1821 /* gather all new values from the
1824 /* or via tty input.*/
1826 for(count = (2+noprompt), pointer = (unsigned char*) &ccontrolnew;
1827 count < argc; ++count, ++pointer)
1831 *pointer = atoi(argv[count]);
1835 pointer = (unsigned char*) &ccontrolnew;
1837 pointerold = (unsigned char*) &ccontrolold;
1839 while(*promptpointer)
1843 fprintf(stderr, "%s [%2.2x/%2.2x]: ",*promptpointer, *pointerold,
1852 if(count = read(0, buffer, 150), count <= 0)
1860 buffer[count] = '\0';
1862 if(buffer[0] != '\n')
1866 sscanf(buffer, "%x", &value);
1868 *pointer = (unsigned char) value;
1878 fprintf(stderr, "\n");
1890 /* This ioctl does the actual register
1893 if(ioctl(fd, ATIS_IOCSPARAMS, &ccontrolnew) < 0)
1897 perror("ioctl failed.");
1918 This program sets the custom baud rate of a serial port. If the custom
1919 baud rate of a serial port is non-zero, and if the standard baud rate
1920 has been set to 38,400 bps, the next time the port is initialized, the
1921 port will run at the custom baud rate. If the custom baud rate were 0,
1922 the port would run at the standard baud rate. The 8352xpeed program is
1923 invoked with a TTY device (either asynchronous, synchronous or callout),
1924 but the effect also applies to the network device and the synchronous
1925 character device that correspond to the same physical serial port.
1929 Here is the source code for the 8253xspeed.
1935 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1939 * This program is free software; you can redistribute it and/or
1941 * modify it under the terms of the GNU General Public License
1943 * as published by the Free Software Foundation; either version
1945 * 2 of the License, or (at your option) any later version.
1953 #include <sys/types.h>
1955 #include <sys/stat.h>
1963 #include "8253xioc.h"
1969 int main(int argc, char **argv)
1975 unsigned long oldspeed, newspeed;
1993 fprintf(stderr, "Syntax: %s {portname} [-n] {new speed}.\n", *argv);
1999 fd = open(argv[1], O_RDWR);
2005 perror("open failed.");
2013 if((argc > 2) && !strcmp("-n", argv[2]))
2024 /* get the current values */
2026 if(ioctl(fd, ATIS_IOCGSPEED, &oldspeed) < 0)
2030 perror("ioctl failed.");
2037 /* set up the existing values as defaults */
2039 newspeed = oldspeed;
2042 /* gather all new values from the command line */
2045 /* or via tty input.*/
2047 if(argc == (noprompt + 3))
2051 newspeed = atoi(argv[count]);
2057 fprintf(stderr, "speed [%ld/%ld]: ", oldspeed, newspeed);
2065 if(count = read(0, buffer, 150), count <= 0)
2076 buffer[count] = '\0';
2078 if(buffer[0] != '\n')
2084 sscanf(buffer, "%ld", &newspeed);
2095 fprintf(stderr, "\n");
2102 /* This ioctl does the actual register load. */
2104 if(ioctl(fd, ATIS_IOCSSPEED, &newspeed) < 0)
2108 perror("ioctl failed.");
2122 The ATIS_IOCGSPEED gets the value the custom baud rate for a serial port
2123 while ATIS_IOCSSPEED sets the value of the custom baud rate for a serial
2135 The 8253xpeer example program reads and writes packets to the serial
2136 port in synchronous mode. The synchronous character driver to some
2137 extent emulates the getmsg/putmsg functionality found in Solaris. This
2138 driver returns only one packet at a time to read and returns ENOMEM if
2139 the receive buffer is not large enough to receive the current packet.
2140 The driver assumes that the data from a write is to be packetized into a
2141 single packet. The driver can provide asynchronous notification that
2142 there is no more data queued to be transmitted at the serial port. This
2143 asynchronous notification informs the application program that a low
2144 priority packet can now be written to the driver. Such functionality is
2145 useful to protocols like LAPB that distinguish low priority information
2146 frames from high priority control frames.
2150 To try out this program find the major device number associated with the
2151 8253xc device in the /proc/devices file. Select two ports to loop
2152 together. Connect them with a synchronous loopback cable. Then execute
2153 the following command for each of the ports.
2157 mknod /dev//DevName1/ c /major-dev-num minor-dev-num-1/
2161 mknod /dev//DevName2/ c /major-dev-num minor-dev-num-2/
2165 Minor-dev-num-[1/2] correspond to the selected ports.
2169 Select one of the ports to be clocking (the clocking end of the loopback
2170 cable should connect to this port) and apply MAKECLOCKING to the
2171 corresponding TTY. Use stty or 8253xspeed and stty to set the speed on
2172 the corresponding TTY port.
2176 Then in one window run *8253xpeer /dev//DevName1/* and in another window
2177 execute *8253xpeer /dev//DevName2./* It should now be possible to send
2178 and receive data in each of the windows.
2182 Here is the program source.
2188 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
2192 * This program is free software; you can redistribute it and/or
2194 * modify it under the terms of the GNU General Public License
2196 * as published by the Free Software Foundation; either version
2198 * 2 of the License, or (at your option) any later version.
2206 #include <sys/types.h>
2208 #include <sys/stat.h>
2216 #include "8253xioc.h"
2218 #include <sys/poll.h>
2222 struct pollfd pollarray[2];
2232 int main(int argc, char **argv)
2250 fprintf(stderr, "Syntax: %s {portname}\n", *argv);
2256 fd = open(argv[1], O_RDWR);
2262 perror("open failed.");
2276 printf("Enter data: ");
2284 pollarray[0].fd = 0;
2286 pollarray[0].events = POLLIN;
2288 pollarray[0].revents = 0;
2290 pollarray[1].fd = fd;
2292 pollarray[1].events = POLLIN|POLLOUT;
2294 pollarray[1].revents = 0;
2296 status = poll(pollarray, 2, 10);
2312 if(pollarray[0].revents == POLLIN)
2316 if(count = read(0, buffer, 150), count <= 0)
2320 perror("unable to read stdio.\n");
2326 buffer[count] = '\0';
2332 if(pollarray[1].revents & POLLOUT)
2336 if(write(pollarray[1].fd, buffer, count) <= 0)
2340 perror("unable to write protodevice.\n");
2352 printf("Write of protodevice would block.\n");
2364 if(pollarray[1].revents & POLLIN)
2368 if(count = read(pollarray[1].fd, buffer, 8192), count <= 0)
2372 perror("unable to read protodevice.\n");
2378 buffer[count] = '\0';
2380 printf("\nRead: %s", buffer);
2413 The 8253xmode program sets the signaling mode of port on a multichannel
2414 server 3500 extension board which has a programmable Sipex sp502
2415 physical driver chip for each port.
2419 The command syntax is the following
2423 *8253xmode* /dev//{dev name} {mode}/
2427 where mode is one of the following.
2438 Note the minor devices associated with a multiserver increase
2439 monotonically starting from the first connector on the upper left corner
2440 if you are facing the connector side of the multiserver. The numbering
2441 goes from left to right and top to bottom without gaps Thus, the
2442 numbers on the multiserver itself may not map to the minor device number
2443 as port number + minor device number of first port if the multiserver is
2444 not fully populated.
2448 Here is the source for the 8253xmode program.
2452 /* -*- linux-c -*- */
2456 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
2460 * This program is free software; you can redistribute it and/or
2462 * modify it under the terms of the GNU General Public License
2464 * as published by the Free Software Foundation; either version
2466 * 2 of the License, or (at your option) any later version.
2474 #include <sys/types.h>
2476 #include <sys/stat.h>
2484 #include "8253xioc.h"
2488 static char *signaling[] =
2510 /* This application shows how to set sigmode
2512 * on those devices that support software
2514 * programmable signaling. */
2516 int main(int argc, char **argv)
2522 unsigned int oldmode, newmode;
2530 fprintf(stderr, "Syntax: %s {portname} {new mode}.\n",
2533 fprintf(stderr, "{new mode} = off | 232 | 422 | 485 |
2534 449 | 530 | v.35\n");
2540 fd = open(argv[1], O_RDWR);
2546 perror("open failed.");
2552 if(!strcmp("off", argv[2]))
2556 newmode = SP502_OFF_MODE;
2560 else if(!strcmp("232", argv[2]))
2564 newmode = SP502_RS232_MODE;
2568 else if(!strcmp("422", argv[2]))
2572 newmode = SP502_RS422_MODE;
2576 else if(!strcmp("485", argv[2]))
2580 newmode = SP502_RS485_MODE;
2584 else if(!strcmp("449", argv[2]))
2588 newmode = SP502_RS449_MODE;
2592 else if(!strcmp("530", argv[2]))
2596 newmode = SP502_EIA530_MODE;
2600 else if(!strcmp("v.35", argv[2]))
2604 newmode = SP502_V35_MODE;
2612 fprintf(stderr, "Unknown mode %s.\n", argv[2]);
2614 fprintf(stderr, "Syntax: %s {portname} {new mode}.\n",
2617 fprintf(stderr, "{new mode} = off | 232 | 422 | 485 |
2618 449 | 530 | v.35\n");
2626 /* get the current values */
2628 if(ioctl(fd, ATIS_IOCGSIGMODE, &oldmode) < 0)
2632 perror("ATIS_IOCGSIGMODE ioctl failed.");
2638 fprintf(stderr, "old mode = %s.\n", signaling[oldmode]);
2642 if(ioctl(fd, ATIS_IOCSSIGMODE, &newmode) < 0)
2646 perror("ATIS_IOCSSIGMODE ioctl failed.");
2654 /* get the current values */
2656 if(ioctl(fd, ATIS_IOCGSIGMODE, &oldmode) < 0)
2660 perror("ATIS_IOCGSIGMODE ioctl failed.");
2666 fprintf(stderr, "new mode = %s.\n", signaling[oldmode]);
2674 The 8253xmode program uses the ATIS_IOCSSIGMODE ioctl to set the new
2675 physical signaling mode and employs the ATIS_IOCGSIGMODE ioctl to get
2676 the original value and to verify the new mode.
2681 _Logic Structure of the ASLX Driver_
2686 /Data Structure Summary/
2690 The key data structures that enable the driver logic are:
2694 1. SAB_BOARD structure ^Ö driver specific
2696 2. SAB_CHIP structure ^Ö driver specific
2698 3. SAB_PORT structure ^Ö driver specific
2700 4. AURA_CIM structure ^Ö driver specific (actually specific to the
2701 multichannel server)
2703 5. RING_DESCRIPTOR ^Ö used by all the driver functionalities in the
2704 transmission of data.
2706 6. DCONTROL2 ^Ö used by all the driver functionalities in managing
2707 the transmission of data.
2709 7. struct sk_buff_head ^Ö two buffer lists are associated with the
2710 SAB_PORT structure are used to track all the sk_buffs that are currently
2711 in use at each port.
2713 8. struct tty_struct ^Ö one per port, standard structure by which
2714 the TTY driver access low level routines for either asynchronous TTY,
2715 synchronous TTY and callout functionality. The SAB_PORT serves as the
2716 private data structure associated with each 8253x TTY, which on a given
2717 open can instantiate itself as a synchronous TTY, an asynchronous TTY or
2718 as a call out device.
2720 9. struct net_device ^Ö one per port, standard network device
2721 structure. The SAB_PORT serves as the private data structure associated
2722 with each 8253x network interface.
2724 10. struct file_operations ^Ö one per port, standard character device
2725 structure. The SAB_PORT serves as the private data structure associated
2726 with each 8253x character interface.
2730 Thus the fundamental driver functionalities, the TTY device, the network
2731 interface and the character device, share the port structure; and the
2732 port structure contains the data is used to arbitrate driver
2733 functionality access to a given physical port. All the above driver
2734 specific structures are dynamically allocated at driver initialization.
2735 They are maintained on lists (in come cases several lists, e.g., global,
2736 per board, by interrupt+by board type and per chip lists). The global
2737 port list is used to map minor device numbers sequentially to ports.
2738 The per chip port list is used in interrupt processing. Likewise the by
2739 interrupt+by board type board lists are also used in interrupt processing.
2743 The use and definition of the tty_struct (TTY and callout drivers),
2744 net_device (network drivers) and file_operations (character drivers)
2745 structures are found in the Linux.
2751 Quick Overview of Standard Linux TTY, Network and Character Devices
2752 and Interaction with the ASLX Driver Design
2756 The basic design of TTY/callout drivers, network drivers and character
2757 drivers is specified by the Linux interface.
2761 The TTY driver uses the standard circular transmit buffer as found in
2762 serial.c, which handles the PC com ports) while received characters pass
2763 into a line disciple via the standard flip buffer logic found in serial.c
2767 The network and character driver parts just follow the design described
2768 in /Linux Device Drivers/ by Alessandro Rubini.
2770 All the driver functionalities use a circular transmit buffer descriptor
2771 ring and sk_buffers for receiving and transmitting data. This uniform
2772 approach to transception simplifies the driver logic immensely.
2776 There is no use of a transmit done interrupt equivalent (unnecessary for
2777 a non-dma design). The driver can be compiled to free up transmitted
2778 sk_buffs in the interrupt handler or in write routines. Investigation
2779 shows that the driver performs better when transmitted buffers are freed
2780 outside of the interrupt handlers. The sk_* routines are in general
2781 fairly performance costly. As a further optimization, when sk_buffs are
2782 freed in the write routines, if system write gets ahead of the
2783 transmitter, the program logic will try to avoid releasing transmitted
2784 buffers (in the TTY driver) but will try to reuse them if possible.
2788 When data is received, chains of receive buffers are passed back to the
2789 character device read routine or to a flush-to-line-discipline function
2790 (defined in the ASLX driver to override the default flush_to_ldisc
2791 routine defined in tty_io.c) in the case of the TTY driver
2792 functionalities. The network driver just invokes the /netif_rx()/
2793 routine at interrupt level to receive packets. Currently, the network
2794 driver pre-allocates a receive buffer, but such pre-allocation is not
2795 necessary, and no other driver functionalities make use of
2796 pre-allocation of buffers.
2799 From Standard Driver Architectures to the ASLX Driver
2803 The main difficulties to be overcome in the ASLX design fit into two
2808 1. No other Linux driver attempts to combine multiple TTY
2809 functionalities with network and character driver functionalities.
2811 2. Even though the members of this Aurora product line all use
2812 basically the same Siemens/Infineon interface chip, the details of
2813 accessing this chip differ radically over the product line. The adapter
2814 cards use the PLX 9050 PCI bridge chip while the multichannel servers
2815 use the AMCC 5920 PCI bridge chip. In the latter case there is a
2816 somewhat complex G-Link hardware protocol used for communication between
2817 the host adapter card and the expansion chassis that hosts the extension
2818 boards where the serial interface chips are located. The adapter cards
2819 differ in detecting and causing modem signal changes.
2824 /Creating a Uniform Device Programming Interface/
2828 The most painful aspect of of creating a multifunction driver for the
2829 Aurora hardware is the difference of each Aurora adapter card or unit
2830 from every other Aurora adapter card or unit.
2834 Signals are handled differently on ESCC2 (SAB82532) versus ESCC8
2835 (SAB82538) based devices. Interrupt processing is different on ESCC2,
2836 ESCC8 and multichannel server devices. The multichannel servers use an
2837 AMCC bridge chip while the other devices use a PLX bridge chip.
2838 Multichannel servers and all other Aurora adapter cards access device
2839 registers completely differently.
2843 There are a set of data structures and macros that simplify access to
2844 control registers for serial ports and that try to provide uniformity in
2845 line control signal handling, which is complex because some signals are
2846 defined in the serial port interface of the 8253X serial interface chip
2847 while other signals are handled through the general parallel ports of
2852 The bitwise definition of the line control signals differ on the
2853 parallel ports of the 82532 and the 82538 based cards (including
2854 multichannel server units).
2858 The macros (courtesy Francois Wautier) below provide a common interface
2859 for raising and lowering control signals as well as for querying them.
2866 * Raise a modem signal y on port x, tmpval must exist! */
2868 #define RAISE(xx,y) \
2872 unsigned char __tmpval__; \
2874 __tmpval__= (xx)->readbyte((xx),(xx)->y.reg);\
2876 if((xx)->y.inverted)\
2878 __tmpval__ &= ~((xx)->y.mask);\
2882 __tmpval__ |= (xx)->y.mask;\
2884 __tmpval__ |= (xx)->y.cnst;\
2888 (xx)->writebyte((xx),(xx)->y.reg,__tmpval__);\
2894 * Lower a modem signal y on port x, __tmpval__ must exist! */
2896 #define LOWER(xx,y) \
2900 unsigned char __tmpval__; \
2902 __tmpval__= (xx)->readbyte((xx),(xx)->y.reg);\
2904 if((xx)->y.inverted)\
2906 __tmpval__ |= (xx)->y.mask;\
2910 __tmpval__ &= ~((xx)->y.mask);\
2912 __tmpval__ |= (xx)->y.cnst;\
2916 (xx)->writebyte((xx),(xx)->y.reg,__tmpval__);\
2922 #define ISON(xx,y) \
2924 ((xx)->y.inverted !=
2925 (((xx)->readbyte((xx),(xx)->y.reg)&(xx)->y.mask)==(xx)->y.mask))
2929 The inverted, cnst, and mask fields of the modem signal structure (y)
2930 are specific to the type of serial communications controller. The
2931 readbyte and writebyte functions are specific to the different types of
2936 To hide the details of accessing control and data registers, the
2937 SAB_PORT structure has a fields whose values are the functions to read a
2938 device register, to write a device register,to read a device FIFO and
2939 to write a device FIFO (as well as to read and to write short words,
2940 functions that could be used in implementing the readfifo and writefifo
2945 Here is readfifo for non-multichannel server hardware.
2949 /***************************************************************************
2951 * aura_readfifo: Function to read the FIFO on a 4X20P, 8X20P or Sun
2960 * port: The port being accessed
2962 * buf: The address of a buffer where we should put
2966 * nbytes: How many chars to read.
2970 * Return value : none
2974 * Prerequisite : The port must have been opened
2986 * Revision : Oct 13 2000, creation
2988 ***************************************************************************/
2990 void aura_readfifo(struct sab_port *port, unsigned char *buf, unsigned
2997 unsigned short *wptr = (unsigned short*) buf;
2999 int nwords = ((nbytes+1)/2);
3001 for(i = 0; i < nwords; i ++)
3005 wptr[i] = readw(((unsigned short *)port->regs));
3013 Here is the readfifo function for multichannel servers.
3017 void wmsaura_readfifo(struct sab_port *port, unsigned char *buf,
3018 unsigned int nbytes)
3024 unsigned short fifo[32/2]; /* this array is word aligned
3026 * buf may not be word aligned*/
3028 unsigned int nwords;
3034 unsigned int address;
3048 wcount = ((nbytes + 1) >> 1);
3050 /* Read the thing into the local FIFO and copy it out. */
3052 address = (unsigned int) port->regs;
3056 for(i = 0; i < wcount; ++i)
3060 fifo[i] = readw((unsigned short*)(address + CIMCMD_RDFIFOW));
3066 memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned
3071 #else /* FIFO_DIRECT */
3073 unsigned short fifo[32/2];
3081 unsigned int channel;
3097 wcount = ((nbytes + 1) >> 1);
3099 channel = (((unsigned char*) port->regs) - bptr->CIMCMD_REG); /*
3100 should be properly shifted */
3106 * Trigger a cache read by writing the nwords - 1 to the
3114 writeb((unsigned char) wcount, bptr->MICCMD_REG + (MICCMD_CACHETRIG +
3121 * Now, read out the contents.
3131 for(i = 0; i < wcount; ++i)
3135 fifo[i] = readw((unsigned short*)(bptr->FIFOCACHE_REG + (channel +
3142 memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned
3145 #endif /* !FIFO_DIRECT */
3152 Except at initialization time the driver code accesses serial
3153 communications controller device registers only through fields in the
3154 port structure. The details of accessing the different types of
3155 hardware are almost completely hidden from the driver program logic.
3159 The only exception is the interrupt handler, which must understand some
3160 of the details of the multichannel server. Nevertheless, as is made
3161 clear in the following section, from the standpoint of processing
3162 interrupts there are really only two types of Aurora hardware, that
3163 which is ESCC2 based and that which is ESCC8 based. The details of the
3164 difference of the two types of hardware is contained solely within the
3165 8253xint.c file which also contains the logic by which an interrupt from
3166 a multichannel server can be processed almost exactly like an interrupt
3167 from an 8520P adapter card.
3172 /Code Structure Summary/
3178 The SAB8253X driver code has the following logic components
3182 1. a probe/initialization logic,
3184 a. bridge initialization/EEPROM parsing logic,
3186 b. structure allocation logic,
3188 c. interrupt request logic,
3190 2. the core logic, which handles all the non-interrupt processing
3191 of the driver functionality,
3193 a. per port startup/shutdown logic,
3195 b. driver arbitration logic,
3197 c. skbuffer management logic,
3199 3. the interrupt handler logic,
3201 a. common interrupt port polling logic,
3203 b. skbuffer management logic,
3205 4. the termination/driver unload logic,
3207 a. interrupt shutdown logic,
3209 b. device shutdown logic,
3211 c. structure deallocation logic.
3217 /Probe/Initialization Logic/
3221 The probe/initialization logic sets up the CRC structures for the
3222 network driver and then the tty_struct for the synchronous and
3223 asynchronous TTY drivers. Initializing the tty_struct involves setting
3224 up pointers to the standard functions that the Linux TTY driver invokes
3225 as well as some standard data and the /proc/tty/driver/auraserial
3231 The probe/initialization logic identifies all the multiport serial
3232 adapters, compact PCI adapters and multiserver adapters in the system
3233 and puts them on a list of board structures. After identifying all the
3234 boards, initializing the bridge chips and analyzing (possibly rewriting)
3235 the serial EEPROM, the logic sets up all the chips on the boards and all
3236 the ports on the chips.
3240 All chips are linked together in a list. All ports are linked together
3241 in a list. The port list is linked together so that minor device N
3242 corresponds to the Nth element of the port list. A board structure
3243 points to a list of chips on the board as well as a list of all ports on
3244 the board. Likewise a chip structure points to a list of all ports on
3245 the chip. Chip structures point back to the board structure associated
3246 with the board on which the chip resides. Likewise port structures
3247 point back to the board and to the chip on which they reside. This
3248 interconnected list structure facilitates access to one type of
3249 structure when a routine has been passed a pointer to another type of
3250 structure. All these structures are dynamically allocated via
3251 /kmalloc()/. When the driver is unloaded, memory is released by walking
3256 After setting up the board, chip and port structures, initialization of
3257 the tty_struct is completed at this point because the maximum possible
3258 number of serial TTYs is now known. The, the standard network device
3259 structure that is associated with each port is allocated and
3260 initialized. The network devices point to the associated port
3261 structure. The network devices are chained via a pointer in the
3262 associated port structure. This chaining facilitates release of the
3263 network device structure memory when the driver is unloaded.
3267 Each network device is registered after its network device structure is
3268 initialized. Network device initialization invokes the network device
3269 initialization, which installs the standard network functions in the
3270 network device structure and which sets up the sk_buff transmit ring as
3271 well as the receive sk_buf. Unlike the Solaris driver, when a complete
3272 frame is received with no errors, it is immediately passed into the
3273 network layer. Thus, there is no receive ring of sk_buffs as one might
3274 find in the driver of a device that could carry out chained DMA (e.g. a
3275 DEC Tulip or an Hitachi SCA).
3279 All sk_buffs associated with a network device that are currently in use
3280 by the network driver are linked together in an sk_buff list (viz core
3281 logic). This list facilitates release of all sk_buff associated with a
3282 network device when that network device is shut down. This list may be
3283 a problem if it becomes possible for a single sk_buff to be used
3284 simultaneously by multiple network devices. Currently, sk_buff headers
3285 are not shared among network devices although sk_buff data can be
3286 shared. Thus, for the nonce this logic works correctly.
3290 After completing of network device initialization, the
3291 probe/initialization logic register the character driver. Next, the
3292 probe/initialization creates three lists of boards for each interrupt
3293 (0-31). One list contains 82532 based boards at that interrupt level.
3294 The next list contains 82538 based adapter cards at that interrupt
3295 level. The third list contains all multichannel server units at that
3300 Next the probe/initialization logic checks the lists associated with
3301 each interrupt level. If either list is non-null, the
3302 probe/initialization logic requests that the general interrupt handler
3303 be installed at this interrupt level and then it turns on PLX9050 or
3304 AMCC5920 interrupts (as needed) into the Linux host for each card
3305 associated with that interrupt level. Thus, the interrupt handler polls
3306 all boards/ports at a given interrupt level when the interrupt occurs.
3307 This approach is more efficient that installing one interrupt per board
3308 and avoids some internal Linux limits on the number of interrupt
3309 handlers that can be installed per interrupt.
3313 At this point probe/intialization is complete and any serial port may be
3314 used for asynchronous TTY, synchronous TTY, call out, network device
3315 service or synchronous character device service.
3324 The main problem of the core logic is arbitration of access to the
3325 serial port, when and by which part of the driver a port is started and
3326 when the port is shut down.
3330 The asynchronous callout, asynchronous TTY, synchronous TTY devices,
3331 synchronous character device and network device follow the following rules.
3335 1. If there is an established point-to-point
3336 connection, only the current process or process group that owns the
3337 serial port may open the device.
3339 2. If the asynchronous callout is open, opens of a
3340 single TTY or character device type block until the connection completes.
3342 3. Network device opens never block, and the network
3343 layer opens a network device only once.
3345 4. If a connection that belongs to a TTY device or
3346 character device hangs up, eventually all opens of that device will close.
3348 5. Hangup of on a network device does not guarantee a
3349 close of the device, but a flag bit is set that permits a call out open
3350 to restore the connection (note that a one-to-one map of TTY devices,
3351 callout devices, character devices and network devices is implied.)
3355 The network device open and block_til_ready* functions invoked from TTY
3356 opens enforce this arbitration.
3360 The logic works as follows:
3364 * The cua device associated with a port may only be opened one.
3365 * If a TTY or character device is open, the cua device may not be
3367 * If the cua device is open, the network device cannot be opened and
3368 the TTY or character device block (multiple opens from the same
3369 process or process group are allowed).
3370 * If the network device is open, the TTY or character devices cannot
3371 be opened while the cua device blocks.
3372 * A hangup sends an interrupt to the TTY or character device while
3373 the network device shuts down its port and a (network blocked) cua
3375 * On the close of the cua device, blocked TTY and character devices
3376 proceed and the network device restarts its port.
3380 When an open completes, the transmit_chars, receive_chars, check_status
3381 functions and associated data fields are set in the port structure,
3382 these are used in the interrupt handler that never changes until the
3387 When a port is not in use, the asynchronous version of these fields and
3388 functions are set in the port structure. Some values must be present,
3389 and the asynchronous ones are probably the least dangerous.
3393 Besides the arbitration problem, the core logic addresses buffer
3394 management for the network and character drivers.
3398 The network layer passes a transmit sk_buff to the network driver. The
3399 buffer is inserted in the transmit ring or sets a transmit congestion
3400 flag. In either case, transmit is initialized if not already in
3401 progress. If the sk_buff is successfully inserted, it is also linked
3402 into the driver sk_buff list which tracks all sk_buffs used by the
3403 network driver. On network device close all sk_buffs on the per port
3404 sk_buff list are released. This sk_buff list mechanism is used to avoid
3409 The TTY and character drivers packetize write data in an sk_buff (each
3410 write creates a single sk_buff) and inserts it in the transmit ring if
3411 possible or blocks (returns a failure in the case of TTY drivers).
3412 Transmit sk_buffs are also linked into the driver sk_buff list. This
3413 list is a convenience to assist deallocation during driver close.
3417 The TTY and character drivers also maintains a receive sk_buff list.
3418 When the user application invokes the read system call, the data from
3419 one sk_buff is passed up to the user application (or an error if the
3420 read were not invoked with sufficient buffer space).
3424 The character driver can be configured via IOCTL to send asynchronous
3425 user notification when the transmit ring empties (a design choice for
3426 the standard driver fasync functionality). This character driver design
3427 emulates the Solaris putmsg/getmsg interface as far as possible and
3428 makes it possible to implement in a user application protocols like
3429 LAPB, which require that low priority packets only be queued to the
3430 driver when the driver currently has no frames in the process of
3431 transmission or queued for transmission.
3435 On character device close all sk_buffs on the per port sk_buff and per
3436 port receive sk_buff list are released. This double sk_buff list
3437 mechanism is used to avoid memory leaks.
3441 /Interrupt Handler Logic/
3446 The following code comprises the combined interrupt and board/port
3447 polling logic. The actual handler is /sab8253x_interrupt()/. It
3448 walks through the 82532, adapter 82538 adapter and multichannel
3449 server lists at the interrupt level that is being processed and
3450 invokes inline /sab82532_interrupt()/ and /sab82538_interrupt()/.
3451 Note that it temporary modifies multichannel server lists so that
3452 it like an 8520P adapter card to the /sab8253x_interrupt()/. This
3453 logic works because the granularity of the PCI interrupt
3454 associated with the Aurora hardware is basically either a list of
3455 ESCC2s (the 4520P and 4520CP adapter cards) or a single ESCC8 (an
3456 8520P or one ESCC8 on a multichannel server remote card after the
3457 interrupt status has been queried).
3463 The current interrupt sources are identified and processed. If
3464 any characters are available to be received, they are received one
3465 fifo at a time into the TTY flip buffer (a structure that is
3466 supposed to decrease TTY latency) or into an sk_buf (something
3467 like a Solaris mblk/dblk structure( in the case of the network or
3468 character driver. Then if there are characters in the TTY
3469 circular transmit buffer or in the network or character driver
3470 sk_buff, they are loaded into the transmit fifo, one fifo at a
3471 time. Finally, modem control status is checked. If a hang up is
3472 detected, the serial driver hang up is scheduled at kernel
3473 scheduler priority (a slight difference from the standard serial
3474 driver which processes hang-ups at interrupt level) in order to
3475 avoid certain race conditions in the TTY driver that can occur on
3476 fast machines with many serial ports. /do_serial_hangup()/
3477 invokes the TTY hangup routines in the case of TTY driver. For a
3478 network connection in the event of a line disconnection, carrier
3479 is marked as off on the interface and the blocked cua device is
3480 woken so that it can proceed after the network port has shut down.
3484 static void __inline__ sab82532_interrupt(int irq, void *dev_id, struct
3489 struct sab_port *port;
3491 struct sab_chip *chip=NULL;
3493 struct sab_board *bptr = (struct sab_board*) dev_id;
3495 union sab8253x_irq_status status;
3501 for(chip = bptr->board_chipbase; chip != NULL; chip =
3502 chip->next_by_board)
3506 port= chip->c_portbase;
3508 gis = READB(port, gis); /* Global! */
3514 /* Since the PORT interrupt are global,
3516 * we do check all the ports for this chip
3522 /* A 2 ports chip */
3526 if(!(gis & SAB82532_GIS_MASK))
3530 continue; /* no interrupt on this chip */
3536 if (gis & SAB82532_GIS_ISA0)
3540 status.sreg.isr0 = READB(port, isr0);
3548 status.sreg.isr0 = 0;
3552 if (gis & SAB82532_GIS_ISA1)
3556 status.sreg.isr1 = READB(port, isr1);
3564 status.sreg.isr1 = 0;
3570 if (gis & SAB82532_GIS_PI)
3574 status.sreg.pis = READB(port, pis);
3582 status.sreg.pis = 0;
3592 if (status.images[ISR0_IDX] & port->receive_test)
3596 (*port->receive_chars)(port, &status); /* when the fifo
3599 /* no time to schedule
3606 if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3608 (status.images[port->cts.irq] & port->cts.irqmask) ||
3610 (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3612 (status.images[ISR1_IDX] & port->check_status_test))
3616 (*port->check_status)(port, &status); /* this stuff should
3619 /* be moveable to scheduler */
3627 if (status.images[ISR1_IDX] & port->transmit_test)
3631 (*port->transmit_chars)(port, &status); /* needs to be
3640 /* Get to next port on chip */
3642 port = port->next_by_chip;
3646 if (gis & SAB82532_GIS_ISB0)
3650 status.images[ISR0_IDX] = READB(port, isr0);
3658 status.images[ISR0_IDX] = 0;
3662 if (gis & SAB82532_GIS_ISB1)
3666 status.images[ISR1_IDX] = READB(port,isr1);
3674 status.images[ISR1_IDX] = 0;
3678 /* DO NOT SET PIS. IT was reset! */
3688 if (status.images[ISR0_IDX] & port->receive_test)
3692 (*port->receive_chars)(port, &status);
3696 if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3698 (status.images[port->cts.irq] & port->cts.irqmask) ||
3700 (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3702 (status.images[ISR1_IDX] & port->check_status_test))
3706 (*port->check_status)(port, &status);
3710 if (status.images[ISR1_IDX] & port->transmit_test)
3714 (*port->transmit_chars)(port, &status);
3726 static void __inline__ sab82538_interrupt(int irq, void *dev_id, struct
3731 struct sab_port *port;
3733 struct sab_chip *chip=NULL;
3735 struct sab_board *bptr = (struct sab_board*) dev_id;
3737 union sab8253x_irq_status status;
3739 unsigned char gis,i;
3743 chip = bptr->board_chipbase;
3745 port= chip->c_portbase;
3749 gis = READB(port, gis); /* Global! */
3755 /* Since the PORT interrupt are global,
3757 * we do check all the ports for this chip
3765 if(!(gis & SAB82538_GIS_MASK))
3775 if(gis & SAB82538_GIS_CII)
3777 { /* A port interrupt! */
3785 portindex = (gis & SAB82538_GIS_CHNL_MASK);
3789 port = chip->c_portbase;
3797 port = port->next_by_chip;
3805 status.images[ISR0_IDX] = READB(port,isr0);
3807 status.images[ISR1_IDX] = READB(port,isr1);
3809 if (gis & SAB82538_GIS_PIC)
3813 status.images[PIS_IDX] =
3815 (*port->readbyte)(port,
3817 ((unsigned char *)(port->regs)) +
3819 SAB82538_REG_PIS_C);
3827 status.images[PIS_IDX] = 0;
3837 if (status.images[ISR0_IDX] & port->receive_test)
3841 (*port->receive_chars)(port, &status);
3845 if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3847 (status.images[port->cts.irq] & port->cts.irqmask) ||
3849 (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3851 (status.images[ISR1_IDX] & port->check_status_test))
3855 (*port->check_status)(port, &status);
3861 * We know that with 8 ports chip, the bit corresponding to
3864 * number is used in the parallel port... So we clear it
3870 status.images[PIS_IDX] &= ~(1 << (gis&SAB82538_GIS_CHNL_MASK));
3872 if (status.images[ISR1_IDX] & port->transmit_test)
3876 (*port->transmit_chars)(port, &status);
3888 * Now we handle the "channel interrupt" case. The chip manual for the
3890 * 8 ports chip states that "channel" and "port" interrupt are set
3892 * independently so we still must check the parrallel port
3896 * We should probably redesign the whole thing to be less AD HOC that we
3898 * are now... We know that port C is used for DSR so we only check
3901 * PIS for port C was already recorded in status.images[PIS_IDX], so we
3903 * check the ports that are set
3909 if (status.images[PIS_IDX])
3913 for(i=0, port = chip->c_portbase;
3917 i++, port=port->next_by_chip)
3921 if(status.images[PIS_IDX] & (0x1 << i))
3927 if(port->dsr.inverted)
3931 port->dsr.val = (((*port->readbyte)
3933 (port, port->dsr.reg) &
3935 port->dsr.mask) ? 0 : 1);
3943 port->dsr.val = ((*port->readbyte)(port, port->dsr.reg) &
3953 wake_up_interruptible(&port->delta_msr_wait);
3967 * This is the serial driver's generic interrupt routine
3973 void sab8253x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3977 extern SAB_BOARD *AuraBoardESCC2IrqRoot[];
3979 extern SAB_BOARD *AuraBoardESCC8IrqRoot[];
3981 extern SAB_BOARD *AuraBoardMCSIrqRoot[];
3989 register SAB_BOARD *boardptr;
3991 register unsigned char intrmask;
3995 SAB_CHIP *save_chiplist;
3997 SAB_PORT *save_portlist;
4001 if((irq < 0) || (irq >= NUMINTS))
4005 printk(KERN_ALERT "sab8253x: bad interrupt value %i.\n", irq);
4011 /* walk through all the cards on the interrupt that occurred. */
4013 for(boardptr = AuraBoardESCC2IrqRoot[irq]; boardptr != NULL; boardptr
4014 = boardptr->next_on_interrupt)
4018 sab82532_interrupt(irq, boardptr, regs);
4024 for(boardptr = AuraBoardESCC8IrqRoot[irq]; boardptr != NULL; boardptr
4025 = boardptr->next_on_interrupt)
4029 sab82538_interrupt(irq, boardptr, regs);
4035 for(boardptr = AuraBoardMCSIrqRoot[irq]; boardptr != NULL; boardptr =
4036 boardptr->next_on_interrupt)
4046 writeb(0, (unsigned char*)(boardptr->CIMCMD_REG +
4047 CIMCMD_WRINTDIS)); /* prevent EBs from raising
4050 * any more ints through the
4055 stat = ~(unsigned char) /* active low !!!!! */
4057 readw((unsigned short*)
4059 (((unsigned char*)boardptr->CIMCMD_REG) +
4060 CIMCMD_RDINT)); /* read out the ints */
4062 /* write to the MIC csr to reset the PCI
4065 writeb(0, (unsigned char*)(boardptr->MICCMD_REG +
4066 MICCMD_MICCSR)); /* reset the interrupt generation
4069 * hardware on the host card*/
4071 /* now, write to the CIM interrupt ena
4072 to re-enable interrupt generation */
4074 writeb(0, (unsigned char*)(boardptr->CIMCMD_REG +
4075 CIMCMD_WRINTENA)); /* allow EBs to request ints
4078 * through the host card */
4088 cim = boardptr->b_cimbase; /* cims in reverse order */
4090 for(intrmask = boardptr->b_intrmask;
4094 intrmask <<= 2, stat <<=2)
4102 break; /* no cim no ports */
4106 if((intrmask & 0xc0) == 0) /* means no cim for these ints */
4108 { /* cim not on list do not go to next */
4114 save_portlist = boardptr->board_portbase;
4116 save_chiplist = boardptr->board_chipbase;
4118 /* the goal is temporarily to make the
4121 * look like 8x20 structures -- thus if
4124 * a bug related to escc8s I need fix it in
4126 * only one place. */
4128 switch(stat & 0xc0) /* possible ints */
4138 case 0x80: /* esccB */
4140 chip = cim->ci_chipbase;
4146 printk(KERN_ALERT "aura mcs: missing cim.\n");
4152 chip = chip->next_by_cim;
4158 printk(KERN_ALERT "aura mcs: missing 2nd cim.\n");
4164 port = chip->c_portbase;
4166 boardptr->board_portbase = port;
4168 boardptr->board_chipbase = chip;
4170 sab82538_interrupt(irq, boardptr, regs);
4176 case 0x40: /* esccA */
4178 chip = cim->ci_chipbase;
4184 printk(KERN_ALERT "aura mcs: missing cim.\n");
4190 port = chip->c_portbase;
4192 boardptr->board_portbase = port;
4194 boardptr->board_chipbase = chip;
4196 sab82538_interrupt(irq, boardptr, regs);
4202 case 0xc0: /* esccB and esccA */
4204 chip = cim->ci_chipbase;
4210 printk(KERN_ALERT "aura mcs: missing cim.\n");
4216 port = chip->c_portbase;
4218 boardptr->board_portbase = port;
4220 boardptr->board_chipbase = chip;
4222 sab82538_interrupt(irq, boardptr, regs);
4226 chip = cim->ci_chipbase;
4232 printk(KERN_ALERT "aura mcs: missing cim.\n");
4238 chip = chip->next_by_cim;
4244 printk(KERN_ALERT "aura mcs: missing 2nd cim.\n");
4250 port = chip->c_portbase;
4252 boardptr->board_portbase = port;
4254 boardptr->board_chipbase = chip;
4256 sab82538_interrupt(irq, boardptr, regs);
4262 boardptr->board_portbase = save_portlist;
4264 boardptr->board_chipbase = save_chiplist;
4266 cim = cim->next_by_mcs;
4278 Note that if there is no transmit in process when the
4279 write/hard_start_transmit routine is invoked, transmit is intitiated
4280 from the core logic as if it took place in the interrupt handler. This
4281 approach differs from the ASE driver, which used to force an interrupt,
4282 and then start the transmission. Francois Wautier may have fixed that
4283 logic to start the transmission either in the STREAMS put or service
4288 /Driver Unload Logic/
4292 The driver unload logic inverts the probe intialization logic.
4296 At this point no ports should be in use and in fact every port should
4297 have been put in the 8253x powered down state when each port underwent
4298 its last close (or hangup which can actually complete after a close).
4302 The tty driver is cleaned up, some dynamic TTY data structures are
4303 deallocated, the bottom half associated with this driver is removed and
4304 all TTY ports are deregistered.
4308 The PLX or AMCC interrupts to the Linux host are disabled on each board,
4309 and all interrupt handlers are freed.
4313 Next all board and chip structures are deallocated (including physical
4314 memory to virtual memory mappings associated with PLX9050 or AMCC 5920
4315 and chip registers). Then all network device structures are
4316 deallocated. (Note that all lingering sk_buffs were freed during the
4317 close of the network device, which must have completed before the unload
4318 of the driver module.) And finally the port structures are
4319 deallocated. In deallocating the port structures, network driver
4320 transmit rings and the receive sk_buff descriptor are deallocated if
4321 they are present. (They were only allocated if the port had ever been
4322 used for a network device.) At this point the driver has been
4323 gracefully unloaded.
4327 /* cleanup module/free up virtual memory */
4331 void cleanup_module(void)
4335 SAB_BOARD *boardptr;
4343 extern void sab8253x_cleanup_ttydriver(void);
4347 printk(KERN_ALERT "auraXX50n: unloading AURAXX50 driver.\n");
4351 sab8253x_cleanup_ttydriver(); /* clean up tty */
4355 /* unallocate and turn off ints */
4357 for(intr_val = 0; intr_val < NUMINTS; ++intr_val)
4361 if((AuraBoardESCC2IrqRoot[intr_val] != NULL) ||
4362 (AuraBoardESCC8IrqRoot[intr_val] != NULL))
4366 for(boardptr = AuraBoardESCC2IrqRoot[intr_val]; boardptr !=
4367 NULL; boardptr = boardptr->next_on_interrupt)
4371 writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
4375 for(boardptr = AuraBoardESCC8IrqRoot[intr_val]; boardptr !=
4376 NULL; boardptr = boardptr->next_on_interrupt)
4380 writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
4386 free_irq(intr_val, &AuraBoardESCC2IrqRoot[intr_val]); /* free
4396 handlers were registered
4408 /* disable chips and free board memory*/
4410 while(AuraBoardRoot)
4414 boardptr = AuraBoardRoot;
4416 for(chipptr = boardptr->board_chipbase; chipptr != NULL; chipptr =
4417 chipptr->next_by_board)
4421 (*chipptr->int_disable)(chipptr); /* make sure no ints can
4426 AuraBoardRoot = boardptr->nextboard;
4428 if(boardptr->virtbaseaddress0)
4432 DEBUGPRINT((KERN_ALERT
4434 "auraXX50n: unmapping virtual address %p.\n",
4436 (void*)boardptr->virtbaseaddress0));
4438 iounmap((void*)boardptr->virtbaseaddress0);
4440 boardptr->virtbaseaddress0 = 0;
4444 if(boardptr->virtbaseaddress2)
4448 DEBUGPRINT((KERN_ALERT
4450 "auraXX50n: unmapping virtual address %p.\n",
4452 (void*)boardptr->virtbaseaddress2));
4454 iounmap((void*)boardptr->virtbaseaddress2);
4456 boardptr->virtbaseaddress2 = 0;
4466 while(AuraChipRoot) /* free chip memory */
4470 chipptr = AuraChipRoot;
4472 AuraChipRoot = chipptr->next;
4480 while(Sab8253xRoot) /* free up network stuff */
4486 priv = (SAB_PORT *)Sab8253xRoot->priv;
4488 unregister_netdev(Sab8253xRoot);
4490 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
4492 kfree(Sab8253xRoot.name);
4496 kfree(Sab8253xRoot);
4498 Sab8253xRoot = priv->next_dev;
4504 while(AuraPortRoot) /* free up port memory */
4508 portptr = AuraPortRoot;
4510 AuraPortRoot = portptr->next;
4512 if(portptr->dcontrol2.receive)
4516 kfree(portptr->dcontrol2.receive);
4520 if(portptr->dcontrol2.transmit)
4524 kfree(portptr->dcontrol2.transmit);
4540 The 10 key data structures are shared by all the logic of the system.
4541 The logic enforces both exclusive and cooperative access to the physical
4542 hardware on the basis of certain rules established by the core logic at
4543 device/port open time. While the driver is mostly self-configuring, the
4544 data structure sharing simplifies the user interface because an ioctl to
4545 one driver functionality (e.g., the TTY functionality) configures the
4546 rest of the driver functionality (e.g., the network and character device
4547 functionality). In other words, a single serial port acts virtually as
4548 three arbitrated devices: a TTY device, which may be asynchronous,
4549 synchronous or call out, a network device or a character device. Yet,
4550 except at the time of initialization, time of driver unload and very
4551 early in interrupt processing all hardware details are concealed and the
4552 driver logic is applied to an abstract, simplified port entity. Thus,
4553 the user application interfaces to three abstract virtual devices, which
4554 have a single configuration interface (otherwise it might be possible to
4555 have an inconsistent configuration) and not to a complex real single
4556 port in the context of an equally complex adapter card or unit. This
4557 simplification makes it possible to provide a high degree of serial
4558 functionality across the family of Aurora synchronous/asynchronous PCI
4559 hardware through a straightforward uniform application interface.