import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / net / wan / 8253x / sab8253xds.txt
1 *_Design Specification of SAB8253X ASLX Driver for Linux_*
2
3  
4
5
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:
11
12  
13
14    1. creating a development environment for maintaining and extending
15       the driver,
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.
22
23  
24
25
26   _Development Environment_
27
28  
29
30
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
36       adapter card.
37
38  
39
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.)
44
45  
46
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.
55
56  
57
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].)
64
65  
66
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. 
69
70  
71
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
78 was named frolix.
79
80  
81
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
87 into bad states.
88
89  
90
91 I executed the following commands on the remote gdb host machine.
92
93  
94
95 *ln ^Ös /home/martillo/kernel/linux-2.4.3/include/asm-i386
96 /home/martillo/kernel/linux-2.4.3/include/asm*
97
98 * *
99
100 or
101
102 * *
103
104 *ln ^Ös /home/martillo/kernel/linux-2.4.6/include/asm-i386
105 /home/martillo/kernel/linux-2.4.6/include/asm*
106
107 * *
108
109 *ln ^Ös / /frolix *
110
111  
112
113 I edited the /etc/exports file to contain the following.
114
115  
116
117 /               ylith(rw)
118
119 /               fireball(rw)
120
121 /               bohun(rw)
122
123 /               indefatigable(rw)
124
125  
126
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.
130
131  
132
133 On the frolix, I started NFS with the following commands (contained in a
134 shell script).
135
136  
137
138 */etc/rc.d/init.d/nfs start*
139
140 *exportfs -va*
141
142  
143
144 If it had been a Suse Linux machine, I would have used the yast2 control
145 center to start NFS service.
146
147  
148
149 On ylith, I created an empty directory /frolix and executed the
150 following command.
151
152  
153
154 *mount frolix:/ /frolix*
155
156 * *
157
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.
165
166  
167
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.
171
172  
173
174 From a shell window:
175
176 *xemacs ^Öe shell&*
177
178  
179
180 Inside xemacs:
181
182  
183
184 *cd /frolix/home/martillo/kernel/linux-2.4.3*
185
186  
187
188 or
189
190  
191
192 *cd /frolix/home/martillo/kernel/linux-2.4.6*
193
194  
195
196 Then make sure that linux-2.4.x/include/asm-i386 is symbolically linked to
197 linux-2.4.x/include/asm.
198
199  
200
201 Execute the following emacs command.
202
203  
204
205
206           M-x compile
207
208  
209
210 This command prompts for targets.
211
212  
213
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
219
220  
221
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
226 *insmod* command.
227
228  
229
230 After building the kernel, installing the modules in the /lib tree
231 requires the execution (as root) of
232
233  
234
235 make modules_install
236
237  
238
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
242 following.
243
244  
245
246 cp /frolix/home/martillo/kernel/linux-2.4.6/arch/i386/boot/bzImage
247 /boot/vmlinuz_246
248
249 cp /frolix/home/martillo/kernel/linux-2.4.6/System.map
250 /boot/System.map-2.4.6
251
252 cp /frolix/home/martillo/kernel/linux-2.4.6/.config /boot/vmlinuz_246.config
253
254 cp /frolix/home/martillo/kernel/linux-2.4.6/include/linux/autoconf.h
255 /boot/vmlinuz_246.autoconf.h
256
257 cp /frolix/home/martillo/kernel/linux-2.4.6/include/linux/version.h
258 /boot/vmlinuz_246.version.h
259
260  
261
262 When the kernel comes from a linux-2.4.3 tree, the obvious substitutions
263 of 3 for 6 are required.
264
265  
266
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.
270
271  
272
273 I added the following directives to the lilo.conf file.
274
275  
276
277   image  = /boot/vmlinuz_243
278
279   label  = linux_2.4.3
280
281   root   = /dev/hde7
282
283   optional
284
285  
286
287   image  = /boot/vmlinuz_246
288
289   label  = linux_2.4.6
290
291   root   = /dev/hde7
292
293   optional
294
295  
296
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
301 /dev/hda7.
302
303  
304
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.
308
309  
310
311 The necessary patch can be obtained from kgdb: Source level debugging of
312 linux kernel <http://kgdb.sourceforge.net/downloads.html>.
313
314  
315
316 Now the kernel can be built again with the extra step of configuring for
317 remote gdb support in the kernel configuration menu. 
318
319  
320
321 The following directives should be added to lilo.conf.
322
323  
324
325   image  = /boot/vmlinuz_243
326
327   label  = debug243
328
329   append = "gdb gdbttyS=0 gdbbaud=115200"
330
331   root   = /dev/hde7
332
333   optional
334
335  
336
337   image  = /boot/vmlinuz_246
338
339   label  = debug246
340
341   append = "gdb gdbttyS=0 gdbbaud=115200"
342
343   root   = /dev/hde7
344
345   optional
346
347  
348
349
350       Then lilo can be executed.  On reboot the boot menu will include
351       options for debug243 and debug246.
352
353  
354
355 To test the patch, select one of the debug options.  Then, on the remote
356 gdb host machine execute the following command.
357
358  
359
360 stty 115200 < /dev/ttyS0
361
362  
363
364 Start up an *xemacs* process.  Execute the following commands within
365 *xemacs.*
366
367  
368
369
370           M-x shell
371
372  
373
374 Then within the shell window execute the following command.
375
376  
377
378 cd /frolix/home/martillo/kernel/linux-2.4./X/
379
380 / /
381
382 Then invoke the remote debugger.
383
384  
385
386
387           M-x gdb
388
389  
390
391 Reply to the file prompt with *vmlinux.*
392
393 * *
394
395 In the gdb window, execute the following command.
396
397  
398
399 target remote /dev/ttyS0
400
401  
402
403 The gdb window should break in gdbstub.c which will be displayed in the
404 gdb source window.
405
406  
407
408 At this point, all the basic gdb remote debugging capabilities are ready
409 to use.
410
411  
412
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
415 *script* command.
416
417  
418
419 #Hardware breakpoints in gdb
420
421 #
422
423 #Using ia-32 hardware breakpoints.
424
425 #
426
427 #4 hardware breakpoints are available in ia-32 processors. These breakpoints
428
429 #do not need code modification. They are set using debug registers.
430
431 #
432
433 #Each hardware breakpoint can be of one of the
434
435 #three types: execution, write, access.
436
437 #1. An Execution breakpoint is triggered when code at the breakpoint
438 address is
439
440 #executed.
441
442 #2. A write breakpoint ( aka watchpoints ) is triggered when memory location
443
444 #at the breakpoint address is written.
445
446 #3. An access breakpoint is triggered when memory location at the breakpoint
447
448 #address is either read or written.
449
450 #
451
452 #As hardware breakpoints are available in limited number, use software
453
454 #breakpoints ( br command in gdb ) instead of execution hardware
455 breakpoints.
456
457 #
458
459 #Length of an access or a write breakpoint defines length of the datatype to
460
461 #be watched. Length is 1 for char, 2 short , 3 int.
462
463 #
464
465 #For placing execution, write and access breakpoints, use commands
466
467 #hwebrk, hwwbrk, hwabrk
468
469 #To remove a breakpoint use hwrmbrk command.
470
471 #
472
473 #These commands take following types of arguments. For arguments associated
474
475 #with each command, use help command.
476
477 #1. breakpointno: 0 to 3
478
479 #2. length: 1 to 3
480
481 #3. address: Memory location in hex ( without 0x ) e.g c015e9bc
482
483 #
484
485 #Use the command exinfo to find which hardware breakpoint occured.
486
487  
488
489  
490
491 #hwebrk breakpointno address
492
493 define hwebrk
494
495         maintenance packet Y$arg0,0,0,$arg1
496
497 end
498
499 document hwebrk
500
501         hwebrk breakpointno address
502
503         Places a hardware execution breakpoint
504
505 end
506
507  
508
509 #hwwbrk breakpointno length address
510
511 define hwwbrk
512
513         maintenance packet Y$arg0,1,$arg1,$arg2
514
515 end
516
517 document hwwbrk
518
519         hwwbrk breakpointno length address
520
521         Places a hardware write breakpoint
522
523 end
524
525  
526
527 #hwabrk breakpointno length address
528
529 define hwabrk
530
531         maintenance packet Y$arg0,1,$arg1,$arg2
532
533 end
534
535 document hwabrk
536
537         hwabrk breakpointno length address
538
539         Places a hardware access breakpoint
540
541 end
542
543  
544
545 #hwrmbrk breakpointno
546
547 define hwrmbrk
548
549         maintenance packet y$arg0
550
551 end
552
553 document hwrmbrk
554
555         hwrmbrk breakpointno
556
557         Removes a hardware breakpoint
558
559 end
560
561  
562
563 #exinfo
564
565 define exinfo
566
567         maintenance packet qE
568
569 end
570
571 document exinfo
572
573         exinfo
574
575         Gives information about a breakpoint.
576
577 end
578
579  
580
581 Once the above macros are define, the developer can set hardware
582 breakpoints.
583
584  
585
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.
592
593 loadmodule.sh modulename
594
595  
596
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.
606
607  
608
609 #!/bin/sh
610
611 # This script loads a module on a target machine and generates a gdb script.
612
613 # source generated gdb script to load the module file at appropriate
614 addresses
615
616 # in gdb.
617
618 #
619
620 # Usage:
621
622 # Loading the module on target machine and generating gdb script)
623
624 #       [foo]$ loadmodule.sh <modulename>
625
626 #
627
628 # Loading the module file into gdb
629
630 #       (gdb) source <gdbscriptpath>
631
632 #
633
634 # Modify following variables according to your setup.
635
636 #       TESTMACHINE - Name of the target machine
637
638 #       GDBSCRIPTS - The directory where a gdb script will be generated
639
640 #
641
642 # Author: Amit S. Kale (akale@veritas.com).
643
644 #
645
646 # If you run into problems, please check files pointed to by following
647
648 # variables.
649
650 #       ERRFILE - /tmp/<modulename>.errs contains stderr output of insmod
651
652 #       MAPFILE - /tmp/<modulename>.map contains stdout output of insmod
653
654 #       GDBSCRIPT - $GDBSCRIPTS/load<modulename> gdb script.
655
656  
657
658 TESTMACHINE=ylith
659
660 GDBSCRIPTS=/frolix/home/martillo/kernel/linux-2.4.6
661
662  
663
664 if [ $# -lt 1 ] ; then {
665
666         echo Usage: $0 modulefile
667
668         exit
669
670 } ; fi
671
672  
673
674 MODULEFILE=$1
675
676 MODULEFILEBASENAME=`basename $1`
677
678  
679
680 if [ $MODULEFILE = $MODULEFILEBASENAME ] ; then {
681
682         MODULEFILE=`pwd`/$MODULEFILE
683
684 } fi
685
686  
687
688 ERRFILE=/tmp/$MODULEFILEBASENAME.errs
689
690 MAPFILE=/tmp/$MODULEFILEBASENAME.map
691
692 GDBSCRIPT=$GDBSCRIPTS/load$MODULEFILEBASENAME
693
694  
695
696 function findaddr() {
697
698         local ADDR=0x$(echo "$SEGMENTS" | \
699
700                 grep "$1" | sed 's/^[^ ]*[ ]*[^ ]*[ ]*//' | \
701
702                 sed 's/[ ]*[^ ]*$//')
703
704         echo $ADDR
705
706 }
707
708  
709
710 function checkerrs() {
711
712         if [ "`cat $ERRFILE`" != "" ] ; then {
713
714                 cat $ERRFILE
715
716         } fi
717
718 }
719
720  
721
722 #load the module
723
724 #echo Copying $MODULEFILE to $TESTMACHINE
725
726 #*rcp $MODULEFILE root@${TESTMACHINE}:
727
728  
729
730 echo Loading module $MODULEFILE
731
732 #rsh -l root $TESTMACHINE  /sbin/insmod -m ./`basename $MODULEFILE` \
733
734 #       > $MAPFILE 2> $ERRFILE &
735
736 /sbin/insmod -m ./`basename $MODULEFILE` $2 . .  > $MAPFILE 2> $ERRFILE &
737
738 sleep 5
739
740 checkerrs
741
742  
743
744 NUMLINES=`grep -n '^$' $MAPFILE | sed -e 's/:.*//g'`
745
746 SEGMENTS=`head -n $NUMLINES $MAPFILE | tail -n $(eval expr $NUMLINES - 1)`
747
748 TEXTADDR=$(findaddr "\\.text[^.]")
749
750 LOADSTRING="add-symbol-file $MODULEFILE $TEXTADDR"
751
752 SEGADDRS=`echo "$SEGMENTS" | awk '//{
753
754         if ($1 != ".text" && $1 != ".this" &&
755
756             $1 != ".kstrtab" && $1 != ".kmodtab") {
757
758                 print " -s " $1 " 0x" $3 " "
759
760         }
761
762 }'`
763
764 LOADSTRING="$LOADSTRING $SEGADDRS"
765
766 echo Generating script $GDBSCRIPT
767
768 echo $LOADSTRING > $GDBSCRIPT
769
770  
771
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>.*
786
787  
788
789
790   _Integration into the Kernel Sources_
791
792
793    
794
795 The driver has its own directory, {kernel root
796 directory}/drivers/net/wan/8253x, in the 2.4.* kernel source tree.
797
798  
799
800 To facilitate the automatic build of the 8253x driver, the following
801 standard kernel files were modified.
802
803  
804
805 1.                  {kernel root directory}/drivers/net/wan/Config.in to
806 which the line
807
808  
809
810 tristate '  Aurora Technology, Inc. synchronous asynchronous PCI cards
811 V2' CONFIG_ATI_XX20
812
813
814  
815
816 was added,
817
818 2.                  {kernel root directory}/drivers/net/wan/Makefile to
819 which the following lines were added,
820
821  
822
823 subdir-$(CONFIG_ATI_XX20) += 8253x
824
825  
826
827 ifeq ($(CONFIG_ATI_XX20),y)
828
829   obj-y += 8253x/ASLX.o
830
831 endif
832
833  
834
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.
838
839  
840
841 module_init(auraXX20_probe);
842
843 module_exit(auraXX20_cleanup);
844
845  
846
847 The sources are provided to the users in a patch file, tentatively named
848 8253x.patch <http://www.telfordtools.com/sab8253x/8253x.patch>.
849
850  
851
852 To install it the user sets his directory to the top level of the kernel
853 sources and executes the following command.
854
855  
856
857 patch ^Öp1 < /{directory-patch}//8253x.patch
858
859
860    
861
862
863   _File Structure of the ASLX Driver Source Code_
864
865  
866
867 The following files are present in the driver directory.
868
869  
870
871 8253x.h
872
873 8253xdbg.c
874
875 8253xmac.c
876
877 8253xsyn.c
878
879 PciRegs.h
880
881 crc32.h
882
883 sp502.h
884
885 8253xcfg.c
886
887 8253xini.c
888
889 8253xnet.c
890
891 8253xtty.c
892
893 Reg9050.h
894
895 crc32dcl.h
896
897 ring.h
898
899 8253xctl.h
900
901 8253xioc.h
902
903 8253xplx.c
904
905 8253xint.c
906
907 crc32.c
908
909 endian.h
910
911 Makefile
912
913 Amcc5920.c
914
915 8253xmcs.h
916
917 8253xmcs.c
918
919 8253xchr.c
920
921 8253xutl.c
922
923  
924
925  
926
927  
928
929 The source code is divided functionally among the files of the ASLX driver.
930
931  
932
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.
936
937  
938
939 8253xini.c contains the initialization/probe logic.
940
941  
942
943 8253xint.c contains the common interrupt logic.
944
945  
946
947 8253xtty.c contains the asynchronous TTY logic.
948
949  
950
951 8253xsyn.c contains the synchronous TTY logic.
952
953  
954
955 8253xnet.c contains the network driver logic.
956
957  
958
959 8253xchr.c contains the character driver logic.
960
961
962  
963
964 8253xdbg.c contains some debugging functions.
965
966  
967
968 8253xutl.c contains most of the functions that are common among the
969 different driver functional subunits.
970
971  
972
973 8253xplx.c contains some functions specific to the PLX9050 (a PCI bridge
974 chip) and specifically to reading and reprogramming the associated
975 serial EEPROM.
976
977  
978
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.
982
983  
984
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).
989
990  
991
992 crc32.c contains logic to append a CRC32 to a pseudo MAC frame that is
993 generated by the network driver.
994
995  
996
997 8253x.h contains symbols, structures and macros that relate mostly to
998 the 8253x chips and ports.
999
1000  
1001
1002 8253xctl.h contains symbols, structures and macros that relate mostly to
1003 the adapter cards.
1004
1005  
1006
1007 8253xmcs.h contains symbols and structures that relate mostly to the
1008 multichannel server.  A lot of this file relates to G-LINK.
1009
1010  
1011
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.
1015
1016  
1017
1018 8253xioc.h contains symbols and structures that relate to private ioctls.
1019
1020  
1021
1022 PciRegs.h contains symbols and structures that relate to PCI
1023 configuration space.
1024
1025  
1026
1027 Reg9050.h contains symbols and structures that relate to the PLX9050 PCI
1028 interface chip and its serial eprom
1029
1030  
1031
1032 crc32.h, crc32dcl.h and .endian.h contain symbols, structures and macros
1033 that relate to generating a correct CRC32.
1034
1035  
1036
1037 ring.h contains symbols and structures that relate to the network driver
1038 frame transmission ring and frame reception.
1039
1040  
1041
1042 The Makefile is a standard Linux kernel Makefile whose structure is
1043 dictated by the current Linux build formalism.
1044
1045  
1046
1047
1048   _Using the ASLX Driver _
1049
1050
1051    
1052
1053
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
1057   ASLX.o file. 
1058
1059  
1060
1061 The following parameters can be set on the /insmod/ command line.
1062
1063  
1064
1065 MODULE_PARM(xx20_minorstart, "i");/*when statically linked autodected
1066 otherwise 128 by default*/
1067
1068 MODULE_PARM(sab8253xc_major, "i");/*major dev for character device, by
1069 default dynamic */
1070
1071 MODULE_PARM(auraXX20n_debug, "i");/*turns on debugging messages, default
1072 off*/
1073
1074 MODULE_PARM(auraXX20n_name, "s"); /*base network driver name = 8253x000*/
1075
1076 MODULE_PARM(sab8253xn_listsize, "i"); /*transmit ring size default 32*/
1077
1078 MODULE_PARM(sab8253xc_name, "s");/*registered name for char driver =
1079 sab8253xc*/
1080
1081 MODULE_PARM(sab8253x_default_sp502_mode, "i");
1082
1083  
1084
1085
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.
1091
1092 RS232 = 1, RS422 = 2, RS485 = 3, RS449 = 4, EIA530 = 5 and V.35 = 6, as
1093 defined in 8253xioc.h.]
1094
1095  
1096
1097 The MAKETERMS script below parses the /proc/tty/driver/auraserial file
1098 to make the asynchronous TTY device files in the /dev directory.
1099
1100  
1101
1102 TTYDEV=$1
1103
1104 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1105 '/[a-zA-Z]/d' | sed -e 's/://'`
1106
1107  
1108
1109 for i in $MDEVS
1110
1111 do
1112
1113         TTYNAME=/dev/ttyS${TTYDEV}
1114
1115         mknod $TTYNAME c 4 $i
1116
1117         TTYDEV=$((${TTYDEV}+1))
1118
1119 done
1120
1121  
1122
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
1126
1127  
1128
1129 TTYDEV=$1
1130
1131 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1132 '/[a-zA-Z]/d' | sed -e 's/://'`
1133
1134 LEADCHAR=""
1135
1136  
1137
1138 for i in $MDEVS
1139
1140 do
1141
1142         NAME=S${TTYDEV}
1143
1144         TTYNAME=ttyS${TTYDEV}
1145
1146         echo ${LEADCHAR}${NAME}:35:respawn:/sbin/agetty 9600 ${TTYNAME}
1147
1148         TTYDEV=$((${TTYDEV}+1))
1149
1150         if [ -z "$LEADCHAR" ]
1151
1152         then
1153
1154                 LEADCHAR="#"
1155
1156         else
1157
1158                 LEADCHAR=""
1159
1160         fi
1161
1162 done
1163
1164  
1165
1166
1167   If loopback cables are connected between successive TTY ports on each
1168   Aurora adapter card or unit, the command
1169
1170  
1171
1172 cu ^Öl /dev/ttyS{n} ^Ös 9600
1173
1174  
1175
1176 would connect to the login that was spawned on /dev/ttyS{n-1}.
1177
1178  
1179
1180 The script MAKESTERMS (viz below) creates synchronous TTY dev files for
1181 all the Aurora serial ports.
1182
1183  
1184
1185 TTYDEV=$1
1186
1187 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1188 '/[a-zA-Z]/d' | sed -e 's/://'`
1189
1190  
1191
1192 for i in $MDEVS
1193
1194 do
1195
1196         TTYNAME=/dev/sttyS${TTYDEV}
1197
1198         mknod $TTYNAME c 5 $i
1199
1200         TTYDEV=$((${TTYDEV}+1))
1201
1202 done
1203
1204  
1205
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.
1209
1210  
1211
1212 TTYDEV=$1
1213
1214 MDEVS=`cat /proc/tty/driver/auraserial | gawk '{print $1}' | sed -e
1215 '/[a-zA-Z]/d' | sed -e 's/://'`
1216
1217 LEADCHAR=""
1218
1219  
1220
1221 for i in $MDEVS
1222
1223 do
1224
1225         NAME=sS${TTYDEV}
1226
1227         TTYNAME=sttyS${TTYDEV}
1228
1229         echo ${LEADCHAR}${NAME}:35:respawn:/sbin/agetty 9600 ${TTYNAME}
1230
1231         TTYDEV=$((${TTYDEV}+1))
1232
1233         if [ -z "$LEADCHAR" ]
1234
1235         then
1236
1237                 LEADCHAR="#"
1238
1239         else
1240
1241                 LEADCHAR=""
1242
1243         fi
1244
1245 done
1246
1247  
1248
1249
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.
1253
1254  
1255
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.
1259
1260  
1261
1262 echo 8253xcfg $1 -n 64 158 56 4 192 140 15
1263
1264 8253xcfg $1 -n 64 158 56 4 192 140 15
1265
1266  
1267
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.
1276
1277  
1278
1279 At this point, the user could execute the following command to connect
1280 synchronously to the peer synchronous TTY port.
1281
1282  
1283
1284 cu ^Öl /dev/sttyS{n} ^Ös 9600
1285
1286  
1287
1288 To turn off internal clocking use the following command.
1289
1290  
1291
1292 8253xcfg /dev/sttyS? ^Ön 64 152 0 4 0 140 15
1293
1294  
1295
1296 To use an ASLX network device the following commands would be used.
1297
1298  
1299
1300 *MAKECLOCKING /dev/sttyS*/{N} [if the interface is to provide clock]/
1301
1302 *stty */{speed} /*< /dev/sttyS*/{N} [if the interface is to provide clock]/
1303
1304  
1305
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.
1308
1309  
1310
1311 *ifconfig 8253x*/{mdev} /*hw ether*/ {mac address} [as root]/
1312
1313  
1314
1315 [Note that the 8253x{mdev} interface must not be running when the above
1316 command is executed.]
1317
1318  
1319
1320 To set the IP address, use the command.
1321
1322 / /
1323
1324 *ifconfig 8253x*/{mdev} {ipadress} [as root]/
1325
1326  
1327
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.]
1331
1332  
1333
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.
1337
1338  
1339
1340 {mdev} is the minor device number (in decimal, 3 digits including
1341 leading 0s required) associated with /dev/sttyS{N}.//
1342
1343 * *
1344
1345 To disable the network interface use the following command.
1346
1347  
1348
1349 *ifconfig 8253x*/{mdev} /*down*/ [as root]/
1350
1351  
1352
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.
1356
1357  
1358
1359 MAKENONCLOCKING /dev/ttyS{N}
1360
1361  
1362
1363 The shell script contains the following commands.
1364
1365  
1366
1367 echo 8253xcfg $1 -n 64 152 0 4 192 140 255
1368
1369 8253xcfg $1 -n 64 152 0 4 192 140 255
1370
1371  
1372
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.
1381
1382
1383          
1384
1385
1386   _Simple Tools and Example Programs_
1387
1388  
1389
1390 The tools and example programs supplied with the SAB8253X ASLX driver
1391 are the following.
1392
1393 1.      eprom9050
1394
1395 2.      8253xcfg
1396
1397 3.      8253xspeed
1398
1399 4.      8253xpeer
1400
1401 5.      8253xmode
1402
1403
1404     eprom9050
1405
1406  
1407
1408 This program performs the bit-banging necessary to read and to program
1409 the serial eprom of the PLX9050. 
1410
1411  
1412
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.
1417
1418  
1419
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
1422 values.
1423
1424  
1425
1426 Here is the source code of the program.
1427
1428  
1429
1430 /*
1431
1432  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1433
1434  *
1435
1436  * This program is free software; you can redistribute it and/or
1437
1438  * modify it under the terms of the GNU General Public License
1439
1440  * as published by the Free Software Foundation; either version
1441
1442  * 2 of the License, or (at your option) any later version.
1443
1444  *
1445
1446  **/
1447
1448  
1449
1450 #include <sys/types.h>
1451
1452 #include <sys/stat.h>
1453
1454 #include <fcntl.h>
1455
1456 #include <stdio.h>
1457
1458 #include <stdlib.h>
1459
1460 #include "8253xioc.h"
1461
1462 #include "Reg9050.h"
1463
1464  
1465
1466  
1467
1468                                 /* This application shows how to load the */
1469
1470                                 /* channel control, mode and rx frame
1471 length */
1472
1473                                 /* check registers via an ioctl.*/
1474
1475  
1476
1477 int main(int argc, char **argv)
1478
1479 {
1480
1481   int fd;
1482
1483   unsigned short oldeeprom[EPROM9050_SIZE], neweeprom[EPROM9050_SIZE];
1484
1485   char buffer[200];
1486
1487   int count;
1488
1489   int value;
1490
1491   unsigned short *pointer;
1492
1493   unsigned short *pointerold;
1494
1495   int noprompt = 0;
1496
1497   int epromindex;
1498
1499  
1500
1501   if(argc < 2)
1502
1503     {
1504
1505       fprintf(stderr, "Syntax: %s {portname} [-n] {prom values}.\n", *argv);
1506
1507       exit(-1);
1508
1509     }
1510
1511   fd = open(argv[1], O_RDWR);
1512
1513   if(fd < 0)
1514
1515     {
1516
1517       perror("open failed.");
1518
1519       exit(-2);
1520
1521     }
1522
1523  
1524
1525   if((argc > 2) && !strcmp("-n", argv[2]))
1526
1527     {
1528
1529       noprompt = 1;
1530
1531     }
1532
1533  
1534
1535                                 /* get the current values */
1536
1537   if(ioctl(fd, ATIS_IOCGSEP9050, &oldeeprom) < 0)
1538
1539     {
1540
1541       perror("ioctl failed.");
1542
1543       exit(-3);
1544
1545     }
1546
1547                                 /* set up the existing values as defaults */
1548
1549   memcpy(neweeprom, oldeeprom, sizeof(oldeeprom));
1550
1551                                 /* gather all new values from the
1552 command line */
1553
1554                                 /* or via tty input.*/
1555
1556   for(count = (2+noprompt), pointer = neweeprom; count < argc; ++count,
1557 ++pointer)
1558
1559     {
1560
1561       *pointer = atoi(argv[count]);
1562
1563     }
1564
1565   pointer = neweeprom;
1566
1567   pointerold = oldeeprom;
1568
1569   for(epromindex = 0; epromindex < EPROM9050_SIZE; ++epromindex)
1570
1571     {
1572
1573       fprintf(stderr, "LOCATION %i [%4.4x/%4.4x]: ", epromindex,
1574 *pointerold, *pointer);
1575
1576  
1577
1578       if(!noprompt)
1579
1580         {
1581
1582           if(count = read(0, buffer, 150), count <= 0)
1583
1584             {
1585
1586               exit(0);
1587
1588             }
1589
1590           buffer[count] = '\0';
1591
1592           if(buffer[0] != '\n')
1593
1594             {
1595
1596               sscanf(buffer, "%x", &value);
1597
1598               *pointer = (unsigned short) value;
1599
1600             }
1601
1602         }
1603
1604       else
1605
1606         {
1607
1608           fprintf(stderr, "\n");
1609
1610         }
1611
1612       ++pointerold;
1613
1614       ++pointer;
1615
1616     }
1617
1618                                 /* This ioctl does the actual register
1619 load. */
1620
1621   if(ioctl(fd, ATIS_IOCSSEP9050, neweeprom) < 0)
1622
1623     {
1624
1625       perror("ioctl failed.");
1626
1627       exit(-3);
1628
1629     }
1630
1631  
1632
1633   fflush(stdout);
1634
1635 }
1636
1637  
1638
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.
1650
1651  
1652
1653
1654     8253xcfg
1655
1656  
1657
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.
1674
1675  
1676
1677 /*
1678
1679  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1680
1681  *
1682
1683  * This program is free software; you can redistribute it and/or
1684
1685  * modify it under the terms of the GNU General Public License
1686
1687  * as published by the Free Software Foundation; either version
1688
1689  * 2 of the License, or (at your option) any later version.
1690
1691  *
1692
1693  **/
1694
1695  
1696
1697 #include <sys/types.h>
1698
1699 #include <sys/stat.h>
1700
1701 #include <fcntl.h>
1702
1703 #include <stdio.h>
1704
1705 #include <stdlib.h>
1706
1707 #include "8253xioc.h"
1708
1709  
1710
1711 char *prompts[] =
1712
1713   {
1714
1715     "ccr0",
1716
1717     "ccr1",
1718
1719     "ccr2",
1720
1721     "ccr3",
1722
1723     "ccr4",
1724
1725     "mode",
1726
1727     "rlcr",
1728
1729     0
1730
1731   };
1732
1733  
1734
1735                                 /* This application shows how to load the */
1736
1737                                 /* channel control, mode and rx frame
1738 length */
1739
1740                                 /* check registers via an ioctl.*/
1741
1742  
1743
1744 int main(int argc, char **argv)
1745
1746 {
1747
1748   int fd;
1749
1750   struct channelcontrol ccontrolold, ccontrolnew;
1751
1752   char buffer[200];
1753
1754   int count;
1755
1756   int value;
1757
1758   unsigned char *pointer;
1759
1760   unsigned char *pointerold;
1761
1762   char **promptpointer = prompts;
1763
1764   int noprompt = 0;
1765
1766  
1767
1768   if(argc < 2)
1769
1770     {
1771
1772       fprintf(stderr, "Syntax: %s {portname} [-n] [ccr0 [ccr1 [ccr2
1773 [ccr3 [ccr4 [mode [rlcr]]]]]]].\n", *argv);
1774
1775       exit(-1);
1776
1777     }
1778
1779   fd = open(argv[1], O_RDWR);
1780
1781   if(fd < 0)
1782
1783     {
1784
1785       perror("open failed.");
1786
1787       exit(-2);
1788
1789     }
1790
1791  
1792
1793   if((argc > 2) && !strcmp("-n", argv[2]))
1794
1795     {
1796
1797       noprompt = 1;
1798
1799     }
1800
1801  
1802
1803                                 /* get the current values */
1804
1805   if(ioctl(fd, ATIS_IOCGPARAMS, &ccontrolold) < 0)
1806
1807     {
1808
1809       perror("ioctl failed.");
1810
1811       exit(-3);
1812
1813     }
1814
1815                                 /* set up the existing values as defaults */
1816
1817   ccontrolnew = ccontrolold;
1818
1819  
1820
1821                                 /* gather all new values from the
1822 command line */
1823
1824                                 /* or via tty input.*/
1825
1826   for(count = (2+noprompt), pointer = (unsigned char*) &ccontrolnew;
1827 count < argc; ++count, ++pointer)
1828
1829     {
1830
1831       *pointer = atoi(argv[count]);
1832
1833     }
1834
1835   pointer = (unsigned char*) &ccontrolnew;
1836
1837   pointerold = (unsigned char*) &ccontrolold;
1838
1839   while(*promptpointer)
1840
1841     {
1842
1843       fprintf(stderr, "%s [%2.2x/%2.2x]: ",*promptpointer, *pointerold,
1844 *pointer);
1845
1846  
1847
1848       if(!noprompt)
1849
1850         {
1851
1852           if(count = read(0, buffer, 150), count <= 0)
1853
1854             {
1855
1856               exit(0);
1857
1858             }
1859
1860           buffer[count] = '\0';
1861
1862           if(buffer[0] != '\n')
1863
1864             {
1865
1866               sscanf(buffer, "%x", &value);
1867
1868               *pointer = (unsigned char) value;
1869
1870             }
1871
1872         }
1873
1874       else
1875
1876         {
1877
1878           fprintf(stderr, "\n");
1879
1880         }
1881
1882       ++pointerold;
1883
1884       ++pointer;
1885
1886       ++promptpointer;
1887
1888     }
1889
1890                                 /* This ioctl does the actual register
1891 load. */
1892
1893   if(ioctl(fd, ATIS_IOCSPARAMS, &ccontrolnew) < 0)
1894
1895     {
1896
1897       perror("ioctl failed.");
1898
1899       exit(-3);
1900
1901     }
1902
1903  
1904
1905   fflush(stdout);
1906
1907 }
1908
1909  
1910
1911  
1912
1913
1914     8253xspeed
1915
1916  
1917
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.
1926
1927  
1928
1929 Here is the source code for the 8253xspeed.
1930
1931  
1932
1933 /*
1934
1935  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
1936
1937  *
1938
1939  * This program is free software; you can redistribute it and/or
1940
1941  * modify it under the terms of the GNU General Public License
1942
1943  * as published by the Free Software Foundation; either version
1944
1945  * 2 of the License, or (at your option) any later version.
1946
1947  *
1948
1949  **/
1950
1951  
1952
1953 #include <sys/types.h>
1954
1955 #include <sys/stat.h>
1956
1957 #include <fcntl.h>
1958
1959 #include <stdio.h>
1960
1961 #include <stdlib.h>
1962
1963 #include "8253xioc.h"
1964
1965  
1966
1967  
1968
1969 int main(int argc, char **argv)
1970
1971 {
1972
1973   int fd;
1974
1975   unsigned long oldspeed, newspeed;
1976
1977   char buffer[200];
1978
1979   int count;
1980
1981   long value;
1982
1983   int noprompt = 0;
1984
1985   int epromindex;
1986
1987  
1988
1989   if(argc < 2)
1990
1991     {
1992
1993       fprintf(stderr, "Syntax: %s {portname} [-n] {new speed}.\n", *argv);
1994
1995       exit(-1);
1996
1997     }
1998
1999   fd = open(argv[1], O_RDWR);
2000
2001   if(fd < 0)
2002
2003     {
2004
2005       perror("open failed.");
2006
2007       exit(-2);
2008
2009     }
2010
2011  
2012
2013   if((argc > 2) && !strcmp("-n", argv[2]))
2014
2015     {
2016
2017       noprompt = 1;
2018
2019     }
2020
2021  
2022
2023                                                                                                        
2024 /* get the current values */
2025
2026   if(ioctl(fd, ATIS_IOCGSPEED, &oldspeed) < 0)
2027
2028     {
2029
2030       perror("ioctl failed.");
2031
2032       exit(-3);
2033
2034     }
2035
2036                                                                                                        
2037 /* set up the existing values as defaults */
2038
2039   newspeed = oldspeed;
2040
2041                                                                                                        
2042 /* gather all new values from the command line */
2043
2044                                                                                                        
2045 /* or via tty input.*/
2046
2047   if(argc == (noprompt + 3))
2048
2049     {
2050
2051       newspeed = atoi(argv[count]);
2052
2053     }
2054
2055  
2056
2057   fprintf(stderr, "speed [%ld/%ld]: ", oldspeed, newspeed);
2058
2059  
2060
2061   if(!noprompt)
2062
2063     {
2064
2065       if(count = read(0, buffer, 150), count <= 0)
2066
2067                                                                                     
2068 {
2069
2070                                                                                     
2071   exit(0);
2072
2073                                                                                     
2074 }
2075
2076       buffer[count] = '\0';
2077
2078       if(buffer[0] != '\n')
2079
2080                                                                                     
2081 {
2082
2083                                                                                     
2084   sscanf(buffer, "%ld", &newspeed);
2085
2086                                                                                     
2087 }
2088
2089     }
2090
2091   else
2092
2093     {
2094
2095       fprintf(stderr, "\n");
2096
2097     }
2098
2099  
2100
2101                                                                                                        
2102 /* This ioctl does the actual register load. */
2103
2104   if(ioctl(fd, ATIS_IOCSSPEED, &newspeed) < 0)
2105
2106     {
2107
2108       perror("ioctl failed.");
2109
2110       exit(-3);
2111
2112     }
2113
2114  
2115
2116   fflush(stdout);
2117
2118 }
2119
2120  
2121
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
2124 port.
2125
2126  
2127
2128  
2129
2130
2131     8253xpeer
2132
2133  
2134
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.
2147
2148  
2149
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.
2154
2155  
2156
2157 mknod /dev//DevName1/ c /major-dev-num minor-dev-num-1/
2158
2159 / /
2160
2161 mknod /dev//DevName2/ c /major-dev-num minor-dev-num-2/
2162
2163  
2164
2165 Minor-dev-num-[1/2] correspond to the selected ports.
2166
2167  
2168
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.
2173
2174  
2175
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.
2179
2180  
2181
2182 Here is the program source.
2183
2184  
2185
2186 /*
2187
2188  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
2189
2190  *
2191
2192  * This program is free software; you can redistribute it and/or
2193
2194  * modify it under the terms of the GNU General Public License
2195
2196  * as published by the Free Software Foundation; either version
2197
2198  * 2 of the License, or (at your option) any later version.
2199
2200  *
2201
2202  **/
2203
2204  
2205
2206 #include <sys/types.h>
2207
2208 #include <sys/stat.h>
2209
2210 #include <fcntl.h>
2211
2212 #include <stdio.h>
2213
2214 #include <stdlib.h>
2215
2216 #include "8253xioc.h"
2217
2218 #include <sys/poll.h>
2219
2220  
2221
2222 struct pollfd pollarray[2];
2223
2224  
2225
2226  
2227
2228 char buffer[8192];
2229
2230  
2231
2232 int main(int argc, char **argv)
2233
2234 {
2235
2236   int fd;
2237
2238   int status;
2239
2240   int prompt = 1;
2241
2242   int count;
2243
2244  
2245
2246   if(argc != 2)
2247
2248     {
2249
2250       fprintf(stderr, "Syntax: %s {portname}\n", *argv);
2251
2252       exit(-1);
2253
2254     }
2255
2256   fd = open(argv[1], O_RDWR);
2257
2258   if(fd < 0)
2259
2260     {
2261
2262       perror("open failed.");
2263
2264       exit(-2);
2265
2266     }
2267
2268   do
2269
2270     {
2271
2272       if(prompt)
2273
2274         {
2275
2276           printf("Enter data: ");
2277
2278           fflush(stdout);
2279
2280           prompt = 0;
2281
2282         }
2283
2284       pollarray[0].fd = 0;
2285
2286       pollarray[0].events = POLLIN;
2287
2288       pollarray[0].revents = 0;
2289
2290       pollarray[1].fd = fd;
2291
2292       pollarray[1].events = POLLIN|POLLOUT;
2293
2294       pollarray[1].revents = 0;
2295
2296       status = poll(pollarray, 2, 10);
2297
2298       switch(status)
2299
2300         {
2301
2302         case 0:
2303
2304           break;
2305
2306  
2307
2308         case 1:
2309
2310         case 2:
2311
2312           if(pollarray[0].revents == POLLIN)
2313
2314             {
2315
2316               if(count = read(0, buffer, 150), count <= 0)
2317
2318                 {
2319
2320                   perror("unable to read stdio.\n");
2321
2322                   exit(0);
2323
2324                 }
2325
2326               buffer[count] = '\0';
2327
2328               if(count)
2329
2330                 {
2331
2332                   if(pollarray[1].revents & POLLOUT)
2333
2334                     {
2335
2336                       if(write(pollarray[1].fd, buffer, count) <= 0)
2337
2338                         {
2339
2340                           perror("unable to write protodevice.\n");
2341
2342                           exit(-1);
2343
2344                         }
2345
2346                     }
2347
2348                   else
2349
2350                     {
2351
2352                       printf("Write of protodevice would block.\n");
2353
2354                       fflush(stdout);
2355
2356                     }
2357
2358                 }
2359
2360               prompt = 1;
2361
2362             }
2363
2364           if(pollarray[1].revents & POLLIN)
2365
2366             {
2367
2368               if(count = read(pollarray[1].fd, buffer, 8192), count <= 0)
2369
2370                 {
2371
2372                   perror("unable to read protodevice.\n");
2373
2374                   exit(0);
2375
2376                 }
2377
2378               buffer[count] = '\0';
2379
2380               printf("\nRead: %s", buffer);
2381
2382               fflush(stdout);
2383
2384               prompt = 1;
2385
2386             }
2387
2388           break;
2389
2390  
2391
2392         default:
2393
2394           break;
2395
2396         }
2397
2398     }
2399
2400   while(status >= 0);
2401
2402 }
2403
2404  
2405
2406  
2407
2408
2409     8253xmode
2410
2411  
2412
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.
2416
2417  
2418
2419 The command syntax is the following
2420
2421  
2422
2423 *8253xmode* /dev//{dev name} {mode}/
2424
2425  
2426
2427 where mode is one of the following.
2428
2429     * off
2430     * 232
2431     * 422
2432     * 485
2433     * 530
2434     * v.35
2435
2436  
2437
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.
2445
2446  
2447
2448 Here is the source for the 8253xmode program.
2449
2450  
2451
2452 /* -*- linux-c -*- */
2453
2454 /*
2455
2456  * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
2457
2458  *
2459
2460  * This program is free software; you can redistribute it and/or
2461
2462  * modify it under the terms of the GNU General Public License
2463
2464  * as published by the Free Software Foundation; either version
2465
2466  * 2 of the License, or (at your option) any later version.
2467
2468  *
2469
2470  **/
2471
2472  
2473
2474 #include <sys/types.h>
2475
2476 #include <sys/stat.h>
2477
2478 #include <fcntl.h>
2479
2480 #include <stdio.h>
2481
2482 #include <stdlib.h>
2483
2484 #include "8253xioc.h"
2485
2486  
2487
2488 static char *signaling[] =
2489
2490 {
2491
2492         "OFF",
2493
2494         "RS232",
2495
2496         "RS422",
2497
2498         "RS485",
2499
2500         "RS449",
2501
2502         "RS530",
2503
2504         "V.35"
2505
2506 };
2507
2508  
2509
2510                                 /* This application shows how to set sigmode
2511
2512                                  * on those devices that support software
2513
2514                                  * programmable signaling. */
2515
2516 int main(int argc, char **argv)
2517
2518 {
2519
2520         int fd;
2521
2522         unsigned int oldmode, newmode;
2523
2524        
2525
2526         if(argc != 3)
2527
2528         {
2529
2530                 fprintf(stderr, "Syntax: %s {portname} {new mode}.\n",
2531 *argv);
2532
2533                 fprintf(stderr, "{new mode} = off | 232 | 422 | 485 |
2534 449 | 530 | v.35\n");
2535
2536                 exit(-1);
2537
2538         }
2539
2540         fd = open(argv[1], O_RDWR);
2541
2542         if(fd < 0)
2543
2544         {
2545
2546                 perror("open failed.");
2547
2548                 exit(-2);
2549
2550         }
2551
2552         if(!strcmp("off", argv[2]))
2553
2554         {
2555
2556                 newmode = SP502_OFF_MODE;
2557
2558         }
2559
2560         else if(!strcmp("232", argv[2]))
2561
2562         {
2563
2564                 newmode = SP502_RS232_MODE;
2565
2566         }
2567
2568         else if(!strcmp("422", argv[2]))
2569
2570         {
2571
2572                 newmode = SP502_RS422_MODE;
2573
2574         }
2575
2576         else if(!strcmp("485", argv[2]))
2577
2578         {
2579
2580                 newmode = SP502_RS485_MODE;
2581
2582         }
2583
2584         else if(!strcmp("449", argv[2]))
2585
2586         {
2587
2588                 newmode = SP502_RS449_MODE;
2589
2590         }
2591
2592         else if(!strcmp("530", argv[2]))
2593
2594         {
2595
2596                 newmode = SP502_EIA530_MODE;
2597
2598         }
2599
2600         else if(!strcmp("v.35", argv[2]))
2601
2602         {
2603
2604                 newmode = SP502_V35_MODE;
2605
2606         }
2607
2608         else
2609
2610         {
2611
2612                 fprintf(stderr, "Unknown mode %s.\n", argv[2]);
2613
2614                 fprintf(stderr, "Syntax: %s {portname} {new mode}.\n",
2615 *argv);
2616
2617                 fprintf(stderr, "{new mode} = off | 232 | 422 | 485 |
2618 449 | 530 | v.35\n");
2619
2620                 exit(-1);
2621
2622         }
2623
2624        
2625
2626         /* get the current values */
2627
2628         if(ioctl(fd, ATIS_IOCGSIGMODE, &oldmode) < 0)
2629
2630         {
2631
2632                 perror("ATIS_IOCGSIGMODE ioctl failed.");
2633
2634                 exit(-3);
2635
2636         }
2637
2638         fprintf(stderr, "old mode = %s.\n", signaling[oldmode]);
2639
2640        
2641
2642         if(ioctl(fd, ATIS_IOCSSIGMODE, &newmode) < 0)
2643
2644         {
2645
2646                 perror("ATIS_IOCSSIGMODE ioctl failed.");
2647
2648                 exit(-3);
2649
2650         }
2651
2652  
2653
2654         /* get the current values */
2655
2656         if(ioctl(fd, ATIS_IOCGSIGMODE, &oldmode) < 0)
2657
2658         {
2659
2660                 perror("ATIS_IOCGSIGMODE ioctl failed.");
2661
2662                 exit(-3);
2663
2664         }      
2665
2666         fprintf(stderr, "new mode = %s.\n", signaling[oldmode]);
2667
2668         fflush(stdout);
2669
2670 }
2671
2672  
2673
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.
2677
2678  
2679
2680
2681   _Logic Structure of the ASLX Driver_
2682
2683  
2684
2685
2686   /Data Structure Summary/
2687
2688  
2689
2690 The key data structures that enable the driver logic are:
2691
2692  
2693
2694 1.      SAB_BOARD structure ^Ö driver specific
2695
2696 2.      SAB_CHIP structure ^Ö driver specific
2697
2698 3.      SAB_PORT structure ^Ö driver specific
2699
2700 4.      AURA_CIM structure ^Ö driver specific (actually specific to the
2701 multichannel server)
2702
2703 5.      RING_DESCRIPTOR ^Ö used by all the driver functionalities in the
2704 transmission of data.
2705
2706 6.      DCONTROL2 ^Ö used by all the driver functionalities in managing
2707 the transmission of data.
2708
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.
2712
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.
2719
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.
2723
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.
2727
2728  
2729
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.
2740
2741  
2742
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. 
2746
2747
2748      
2749
2750
2751     Quick Overview of Standard Linux TTY, Network and Character Devices
2752     and Interaction with the ASLX Driver Design
2753
2754  
2755
2756 The basic design of TTY/callout drivers, network drivers and character
2757 drivers is specified by the Linux interface. 
2758
2759  
2760
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
2764
2765  
2766
2767 The network and character driver parts just follow the design described
2768 in /Linux Device Drivers/ by Alessandro Rubini.
2769
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.
2773
2774  
2775
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.
2785
2786  
2787
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.
2797
2798
2799     From Standard Driver Architectures to the ASLX Driver
2800
2801  
2802
2803 The main difficulties to be overcome in the ASLX design fit into two
2804 categories.
2805
2806  
2807
2808 1.      No other Linux driver attempts to combine multiple TTY
2809 functionalities with network and character driver functionalities.
2810
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.
2820
2821  
2822
2823
2824   /Creating a Uniform Device Programming Interface/
2825
2826  
2827
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. 
2831
2832  
2833
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.
2840
2841  
2842
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
2848 the 8253X chip. 
2849
2850  
2851
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). 
2855
2856  
2857
2858 The macros (courtesy Francois Wautier) below provide a common interface
2859 for raising and lowering control signals as well as for querying them.
2860
2861
2862    
2863
2864 /*
2865
2866  * Raise a modem signal y on port x, tmpval must exist! */
2867
2868 #define RAISE(xx,y) \
2869
2870 { \
2871
2872           unsigned char __tmpval__; \
2873
2874           __tmpval__= (xx)->readbyte((xx),(xx)->y.reg);\
2875
2876           if((xx)->y.inverted)\
2877
2878             __tmpval__ &= ~((xx)->y.mask);\
2879
2880           else\
2881
2882             __tmpval__ |= (xx)->y.mask;\
2883
2884           __tmpval__ |= (xx)->y.cnst;\
2885
2886           (xx)->y.val=1;\
2887
2888           (xx)->writebyte((xx),(xx)->y.reg,__tmpval__);\
2889
2890 }
2891
2892 /*
2893
2894  * Lower a modem signal y on port x, __tmpval__ must exist! */
2895
2896 #define LOWER(xx,y) \
2897
2898 {\
2899
2900           unsigned char __tmpval__; \
2901
2902           __tmpval__= (xx)->readbyte((xx),(xx)->y.reg);\
2903
2904           if((xx)->y.inverted)\
2905
2906             __tmpval__ |= (xx)->y.mask;\
2907
2908           else\
2909
2910             __tmpval__ &= ~((xx)->y.mask);\
2911
2912           __tmpval__ |= (xx)->y.cnst;\
2913
2914           (xx)->y.val=0;\
2915
2916           (xx)->writebyte((xx),(xx)->y.reg,__tmpval__);\
2917
2918 }
2919
2920  
2921
2922 #define ISON(xx,y) \
2923
2924           ((xx)->y.inverted !=
2925 (((xx)->readbyte((xx),(xx)->y.reg)&(xx)->y.mask)==(xx)->y.mask))
2926
2927  
2928
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
2932 Aurora hardware.
2933
2934  
2935
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
2941 routines).
2942
2943  
2944
2945 Here is readfifo for non-multichannel server hardware.
2946
2947  
2948
2949 /***************************************************************************
2950
2951  * aura_readfifo:    Function to read the FIFO on a 4X20P, 8X20P or Sun
2952 serial
2953
2954  *               
2955
2956  *
2957
2958  *     Parameters   :
2959
2960  *                   port:  The port being accessed
2961
2962  *                   buf:   The address of a buffer where we should put
2963
2964  *                          what we read
2965
2966  *                  nbytes: How many chars to read.
2967
2968  *
2969
2970  *     Return value : none
2971
2972  *
2973
2974  *     Prerequisite : The port must have been opened
2975
2976  *
2977
2978  *     Remark       :
2979
2980  *
2981
2982  *     Author       : fw
2983
2984  *
2985
2986  *     Revision     : Oct 13 2000, creation
2987
2988  ***************************************************************************/
2989
2990 void aura_readfifo(struct sab_port *port, unsigned char *buf, unsigned
2991 int nbytes)
2992
2993 {
2994
2995   int i;
2996
2997   unsigned short *wptr = (unsigned short*) buf;
2998
2999   int nwords = ((nbytes+1)/2);
3000
3001   for(i = 0; i < nwords; i ++)
3002
3003     {
3004
3005       wptr[i] = readw(((unsigned short *)port->regs));
3006
3007     }
3008
3009 }
3010
3011  
3012
3013 Here is the readfifo function for multichannel servers.
3014
3015  
3016
3017 void wmsaura_readfifo(struct sab_port *port, unsigned char *buf,
3018 unsigned int nbytes)
3019
3020 {
3021
3022 #ifdef FIFO_DIRECT
3023
3024   unsigned short fifo[32/2];    /* this array is word aligned
3025
3026                                  * buf may not be word aligned*/
3027
3028   unsigned int nwords;
3029
3030   int i;
3031
3032   int wcount;
3033
3034   unsigned int address;
3035
3036  
3037
3038   if (nbytes == 0)
3039
3040     {
3041
3042       return;
3043
3044     }
3045
3046  
3047
3048   wcount = ((nbytes + 1) >> 1);
3049
3050   /* Read the thing into the local FIFO and copy it out. */
3051
3052   address = (unsigned int) port->regs;
3053
3054  
3055
3056   for(i = 0; i < wcount; ++i)
3057
3058     {
3059
3060       fifo[i] = readw((unsigned short*)(address + CIMCMD_RDFIFOW));
3061
3062     }
3063
3064  
3065
3066   memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned
3067 int) nbytes);
3068
3069  
3070
3071 #else           /* FIFO_DIRECT */
3072
3073   unsigned short fifo[32/2];
3074
3075   int i;
3076
3077   int wcount;
3078
3079   SAB_BOARD *bptr;
3080
3081   unsigned int channel;
3082
3083  
3084
3085   if (nbytes == 0)
3086
3087     {
3088
3089       return;
3090
3091     }
3092
3093  
3094
3095   bptr = port->board;
3096
3097   wcount = ((nbytes + 1) >> 1);
3098
3099   channel = (((unsigned char*) port->regs) - bptr->CIMCMD_REG); /*
3100 should be properly shifted */
3101
3102  
3103
3104   /*
3105
3106    * Trigger a cache read by writing the nwords - 1 to the
3107
3108    *  magic place.
3109
3110    */
3111
3112  
3113
3114   writeb((unsigned char) wcount, bptr->MICCMD_REG + (MICCMD_CACHETRIG +
3115 channel));
3116
3117  
3118
3119   /*
3120
3121    * Now, read out the contents.
3122
3123    */
3124
3125  
3126
3127   channel >>= 1;
3128
3129  
3130
3131   for(i = 0; i < wcount; ++i)
3132
3133     {
3134
3135       fifo[i] = readw((unsigned short*)(bptr->FIFOCACHE_REG + (channel +
3136 (i << 1))));
3137
3138     }
3139
3140  
3141
3142   memcpy((unsigned char*) buf, (unsigned char*) &(fifo[0]), (unsigned
3143 int) nbytes);
3144
3145 #endif          /* !FIFO_DIRECT */
3146
3147 }
3148
3149
3150    
3151
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.
3156
3157  
3158
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.
3168
3169  
3170
3171
3172   /Code Structure Summary/
3173
3174
3175    
3176
3177
3178   The SAB8253X driver code has the following logic components
3179
3180  
3181
3182 1.      a probe/initialization logic,
3183
3184 a.      bridge initialization/EEPROM parsing logic,
3185
3186 b.      structure allocation logic,
3187
3188 c.      interrupt request logic,
3189
3190 2.      the core logic, which handles all the non-interrupt processing
3191 of the driver functionality,
3192
3193 a.      per port startup/shutdown logic,
3194
3195 b.      driver arbitration logic,
3196
3197 c.      skbuffer management logic,
3198
3199 3.      the interrupt handler logic,
3200
3201 a.      common interrupt port polling logic,
3202
3203 b.      skbuffer management logic,
3204
3205 4.      the termination/driver unload logic,
3206
3207 a.      interrupt shutdown logic,
3208
3209 b.      device shutdown logic,
3210
3211 c.      structure deallocation logic.
3212
3213  
3214
3215  
3216
3217 /Probe/Initialization Logic/
3218
3219  
3220
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
3226 function and data.
3227
3228  
3229
3230
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. 
3237
3238  
3239
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
3252 the list. 
3253
3254  
3255
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.
3264
3265  
3266
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).
3276
3277  
3278
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.
3287
3288  
3289
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
3296 interrupt level.
3297
3298  
3299
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.
3310
3311  
3312
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.
3316
3317  
3318
3319
3320 /Core Logic/
3321
3322  
3323
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.
3327
3328  
3329
3330 The asynchronous callout, asynchronous TTY, synchronous TTY devices,
3331 synchronous character device and network device follow the following rules.
3332
3333  
3334
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.
3338
3339 2.                  If the asynchronous callout is open, opens of a
3340 single TTY or character device type block until the connection completes.
3341
3342 3.                  Network device opens never block, and the network
3343 layer opens a network device only once.
3344
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.
3347
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.)
3352
3353  
3354
3355 The network device open and block_til_ready* functions invoked from TTY
3356 opens enforce this arbitration.
3357
3358  
3359
3360 The logic works as follows:
3361
3362  
3363
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
3366       opened.
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
3374       device proceeds.
3375     * On the close of the cua device, blocked TTY and character devices
3376       proceed and the network device restarts its port.
3377
3378  
3379
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
3383 driver is unloaded.
3384
3385  
3386
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.
3390
3391  
3392
3393 Besides the arbitration problem, the core logic addresses buffer
3394 management for the network and character drivers.
3395
3396  
3397
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
3405 memory leaks.
3406
3407  
3408
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.
3414
3415  
3416
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). 
3421
3422  
3423
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.
3432
3433  
3434
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.
3438
3439  
3440
3441 /Interrupt Handler Logic/
3442
3443  
3444
3445
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).
3458
3459
3460        
3461
3462
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.
3481
3482  
3483
3484 static void __inline__ sab82532_interrupt(int irq, void *dev_id, struct
3485 pt_regs *regs)
3486
3487 {
3488
3489   struct sab_port *port;
3490
3491   struct sab_chip *chip=NULL;
3492
3493   struct sab_board *bptr = (struct sab_board*) dev_id;
3494
3495   union sab8253x_irq_status status;
3496
3497   unsigned char gis;
3498
3499  
3500
3501   for(chip = bptr->board_chipbase; chip != NULL; chip =
3502 chip->next_by_board)
3503
3504     {
3505
3506       port= chip->c_portbase;
3507
3508       gis = READB(port, gis); /* Global! */
3509
3510       status.stat=0;
3511
3512      
3513
3514             /* Since the PORT interrupt are global,
3515
3516              * we do check all the ports for this chip
3517
3518              */
3519
3520            
3521
3522                                 /* A 2 ports chip */
3523
3524          
3525
3526       if(!(gis & SAB82532_GIS_MASK))
3527
3528         {
3529
3530           continue; /* no interrupt on this chip */
3531
3532         }
3533
3534          
3535
3536       if (gis & SAB82532_GIS_ISA0)
3537
3538         {
3539
3540           status.sreg.isr0 = READB(port, isr0);
3541
3542         }
3543
3544       else
3545
3546         {
3547
3548           status.sreg.isr0 = 0;
3549
3550         }
3551
3552       if (gis & SAB82532_GIS_ISA1)
3553
3554         {
3555
3556           status.sreg.isr1 = READB(port, isr1);
3557
3558         }
3559
3560       else
3561
3562         {
3563
3564           status.sreg.isr1 = 0;
3565
3566         }
3567
3568          
3569
3570       if (gis & SAB82532_GIS_PI)
3571
3572         {
3573
3574           status.sreg.pis = READB(port, pis);
3575
3576         }
3577
3578       else
3579
3580         {
3581
3582           status.sreg.pis = 0;
3583
3584         }
3585
3586                
3587
3588       if (status.stat)
3589
3590         {
3591
3592           if (status.images[ISR0_IDX] & port->receive_test)
3593
3594             {
3595
3596               (*port->receive_chars)(port, &status);    /* when the fifo
3597 is full */
3598
3599                                                 /* no time to schedule
3600 thread*/
3601
3602             }
3603
3604          
3605
3606           if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3607
3608               (status.images[port->cts.irq] & port->cts.irqmask) ||
3609
3610               (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3611
3612               (status.images[ISR1_IDX] & port->check_status_test))
3613
3614             {
3615
3616               (*port->check_status)(port, &status); /* this stuff should
3617 be */
3618
3619               /* be moveable to scheduler */
3620
3621               /* thread*/
3622
3623             }
3624
3625          
3626
3627           if (status.images[ISR1_IDX] & port->transmit_test)
3628
3629             {
3630
3631               (*port->transmit_chars)(port, &status); /* needs to be
3632 moved to task */
3633
3634             }
3635
3636         }
3637
3638      
3639
3640                                 /* Get to next port on chip */
3641
3642       port = port->next_by_chip;
3643
3644       /* Port B */
3645
3646       if (gis & SAB82532_GIS_ISB0)
3647
3648         {
3649
3650           status.images[ISR0_IDX] = READB(port, isr0);
3651
3652         }
3653
3654       else
3655
3656         {
3657
3658           status.images[ISR0_IDX] = 0;
3659
3660         }
3661
3662       if (gis & SAB82532_GIS_ISB1)
3663
3664         {
3665
3666           status.images[ISR1_IDX] = READB(port,isr1);
3667
3668         }
3669
3670       else
3671
3672         {
3673
3674           status.images[ISR1_IDX] = 0;
3675
3676         }
3677
3678       /* DO NOT SET PIS. IT was reset! */
3679
3680      
3681
3682      
3683
3684       if (status.stat)
3685
3686         {
3687
3688           if (status.images[ISR0_IDX] & port->receive_test)
3689
3690             {
3691
3692               (*port->receive_chars)(port, &status);
3693
3694             }
3695
3696           if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3697
3698               (status.images[port->cts.irq] & port->cts.irqmask) ||
3699
3700               (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3701
3702               (status.images[ISR1_IDX] & port->check_status_test))
3703
3704             {
3705
3706               (*port->check_status)(port, &status);
3707
3708             }
3709
3710           if (status.images[ISR1_IDX] & port->transmit_test)
3711
3712             {
3713
3714               (*port->transmit_chars)(port, &status);
3715
3716             }
3717
3718         }
3719
3720     }
3721
3722 }
3723
3724  
3725
3726 static void __inline__ sab82538_interrupt(int irq, void *dev_id, struct
3727 pt_regs *regs)
3728
3729 {
3730
3731   struct sab_port *port;
3732
3733   struct sab_chip *chip=NULL;
3734
3735   struct sab_board *bptr = (struct sab_board*) dev_id;
3736
3737   union sab8253x_irq_status status;
3738
3739   unsigned char gis,i;
3740
3741  
3742
3743   chip = bptr->board_chipbase;
3744
3745   port= chip->c_portbase;
3746
3747  
3748
3749   gis = READB(port, gis); /* Global! */
3750
3751   status.stat=0;
3752
3753      
3754
3755             /* Since the PORT interrupt are global,
3756
3757              * we do check all the ports for this chip
3758
3759              */
3760
3761            
3762
3763   /* 8 ports chip */
3764
3765   if(!(gis & SAB82538_GIS_MASK))
3766
3767     {
3768
3769       return;
3770
3771     }
3772
3773              
3774
3775   if(gis & SAB82538_GIS_CII)
3776
3777     { /* A port interrupt! */
3778
3779       /* Get the port */
3780
3781       int portindex;
3782
3783      
3784
3785       portindex = (gis & SAB82538_GIS_CHNL_MASK);
3786
3787      
3788
3789       port = chip->c_portbase;
3790
3791      
3792
3793       while(portindex)
3794
3795         {
3796
3797           port = port->next_by_chip;
3798
3799           --portindex;
3800
3801         }
3802
3803      
3804
3805       status.images[ISR0_IDX] = READB(port,isr0);
3806
3807       status.images[ISR1_IDX] = READB(port,isr1);
3808
3809       if (gis & SAB82538_GIS_PIC)
3810
3811         {
3812
3813           status.images[PIS_IDX] =
3814
3815             (*port->readbyte)(port,
3816
3817                               ((unsigned char *)(port->regs)) +
3818
3819                               SAB82538_REG_PIS_C);
3820
3821         }
3822
3823       else
3824
3825         {
3826
3827           status.images[PIS_IDX] = 0;
3828
3829         }
3830
3831      
3832
3833       if (status.stat)
3834
3835         {
3836
3837           if (status.images[ISR0_IDX] & port->receive_test)
3838
3839             {
3840
3841               (*port->receive_chars)(port, &status);
3842
3843             }
3844
3845           if ((status.images[port->dcd.irq] & port->dcd.irqmask) ||
3846
3847               (status.images[port->cts.irq] & port->cts.irqmask) ||
3848
3849               (status.images[port->dsr.irq] & port->dsr.irqmask) ||
3850
3851               (status.images[ISR1_IDX] & port->check_status_test))
3852
3853             {
3854
3855               (*port->check_status)(port, &status);
3856
3857             }
3858
3859           /*
3860
3861            * We know that with 8 ports chip, the bit corresponding to
3862 channel
3863
3864            * number is used in the parallel port... So we clear it
3865
3866            * Not too elegant!
3867
3868            */
3869
3870           status.images[PIS_IDX] &= ~(1 << (gis&SAB82538_GIS_CHNL_MASK));
3871
3872           if (status.images[ISR1_IDX] & port->transmit_test)
3873
3874             {
3875
3876               (*port->transmit_chars)(port, &status);
3877
3878             }
3879
3880         }
3881
3882     }
3883
3884  
3885
3886   /*
3887
3888    * Now we handle the "channel interrupt" case. The chip manual for the
3889
3890    * 8 ports chip states that "channel" and "port" interrupt are set
3891
3892    * independently so we still must check the parrallel port
3893
3894    *
3895
3896    * We should probably redesign the whole thing to be less AD HOC that we
3897
3898    * are now... We know that port C is used for DSR so we only check
3899 that one.
3900
3901    * PIS for port C was already recorded in  status.images[PIS_IDX], so we
3902
3903    * check the ports that are set
3904
3905    */
3906
3907  
3908
3909   if (status.images[PIS_IDX])
3910
3911     {
3912
3913       for(i=0, port = chip->c_portbase;
3914
3915           i < chip->c_nports;
3916
3917           i++, port=port->next_by_chip)
3918
3919         {
3920
3921           if(status.images[PIS_IDX] & (0x1 << i))
3922
3923             { /* Match */
3924
3925               /* Checking DSR */
3926
3927               if(port->dsr.inverted)
3928
3929                 {
3930
3931                   port->dsr.val = (((*port->readbyte)
3932
3933                                     (port, port->dsr.reg) &
3934
3935                                     port->dsr.mask) ? 0 : 1);
3936
3937                 }
3938
3939               else
3940
3941                 {
3942
3943                   port->dsr.val = ((*port->readbyte)(port, port->dsr.reg) &
3944
3945                                    port->dsr.mask);
3946
3947                 }
3948
3949              
3950
3951               port->icount.dsr++;
3952
3953               wake_up_interruptible(&port->delta_msr_wait);
3954
3955             }
3956
3957         }
3958
3959     }
3960
3961 }
3962
3963  
3964
3965 /*
3966
3967  * This is the serial driver's generic interrupt routine
3968
3969  */
3970
3971  
3972
3973 void sab8253x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3974
3975 {
3976
3977   extern SAB_BOARD *AuraBoardESCC2IrqRoot[];
3978
3979   extern SAB_BOARD *AuraBoardESCC8IrqRoot[];
3980
3981   extern SAB_BOARD *AuraBoardMCSIrqRoot[];
3982
3983   AURA_CIM *cim;
3984
3985   SAB_CHIP *chip;
3986
3987   SAB_PORT *port;
3988
3989   register SAB_BOARD *boardptr;
3990
3991   register unsigned char intrmask;
3992
3993   unsigned char stat;
3994
3995   SAB_CHIP *save_chiplist;
3996
3997   SAB_PORT *save_portlist;
3998
3999  
4000
4001   if((irq < 0) || (irq >= NUMINTS))
4002
4003     {
4004
4005       printk(KERN_ALERT "sab8253x: bad interrupt value %i.\n", irq);
4006
4007       return;
4008
4009     }
4010
4011   /* walk through all the cards on the interrupt that occurred. */
4012
4013   for(boardptr = AuraBoardESCC2IrqRoot[irq]; boardptr != NULL; boardptr
4014 = boardptr->next_on_interrupt)
4015
4016     {
4017
4018       sab82532_interrupt(irq, boardptr, regs);
4019
4020     }
4021
4022  
4023
4024   for(boardptr = AuraBoardESCC8IrqRoot[irq]; boardptr != NULL; boardptr
4025 = boardptr->next_on_interrupt)
4026
4027     {
4028
4029       sab82538_interrupt(irq, boardptr, regs);
4030
4031     } 
4032
4033  
4034
4035   for(boardptr = AuraBoardMCSIrqRoot[irq]; boardptr != NULL; boardptr =
4036 boardptr->next_on_interrupt)
4037
4038     {
4039
4040  
4041
4042       while(1)
4043
4044         {
4045
4046           writeb(0, (unsigned char*)(boardptr->CIMCMD_REG +
4047 CIMCMD_WRINTDIS)); /* prevent EBs from raising
4048
4049                                                                                
4050 * any more ints through the
4051
4052                                                                                
4053 * host card */
4054
4055           stat = ~(unsigned char) /* active low !!!!! */
4056
4057             readw((unsigned short*)
4058
4059                   (((unsigned char*)boardptr->CIMCMD_REG) +
4060 CIMCMD_RDINT)); /* read out the ints */
4061
4062                                 /* write to the MIC csr to reset the PCI
4063 interrupt */
4064
4065           writeb(0, (unsigned char*)(boardptr->MICCMD_REG +
4066 MICCMD_MICCSR)); /* reset the interrupt generation
4067
4068                                                                        
4069       * hardware on the host card*/
4070
4071                                 /* now, write to the CIM interrupt ena
4072 to re-enable interrupt generation */
4073
4074           writeb(0, (unsigned char*)(boardptr->CIMCMD_REG +
4075 CIMCMD_WRINTENA)); /* allow EBs to request ints
4076
4077                                                                                
4078 * through the host card */
4079
4080           if(!stat)
4081
4082             {
4083
4084               break;
4085
4086             }
4087
4088           cim = boardptr->b_cimbase; /* cims in reverse order */
4089
4090           for(intrmask = boardptr->b_intrmask;
4091
4092               intrmask != 0;
4093
4094               intrmask <<= 2, stat <<=2)
4095
4096             {
4097
4098               if(cim == NULL)
4099
4100                 {
4101
4102                   break;        /* no cim no ports */
4103
4104                 }
4105
4106               if((intrmask & 0xc0) == 0) /* means no cim for these ints */
4107
4108                 {               /* cim not on list do not go to next */
4109
4110                   continue;
4111
4112                 }
4113
4114               save_portlist = boardptr->board_portbase;
4115
4116               save_chiplist = boardptr->board_chipbase;
4117
4118                                 /* the goal is temporarily to make the
4119 structures
4120
4121                                  * look like 8x20 structures -- thus if
4122 I find
4123
4124                                  * a bug related to escc8s I need fix it in
4125
4126                                  * only one place. */
4127
4128               switch(stat & 0xc0) /* possible ints */
4129
4130                 {
4131
4132                 default:
4133
4134                   break;
4135
4136                  
4137
4138                 case 0x80:      /* esccB */
4139
4140                   chip = cim->ci_chipbase;
4141
4142                   if(!chip)
4143
4144                     {
4145
4146                       printk(KERN_ALERT "aura mcs: missing cim.\n");
4147
4148                       break;
4149
4150                     }
4151
4152                   chip = chip->next_by_cim;
4153
4154                   if(!chip)
4155
4156                     {
4157
4158                       printk(KERN_ALERT "aura mcs: missing 2nd cim.\n");
4159
4160                       break;
4161
4162                     }
4163
4164                   port = chip->c_portbase;
4165
4166                   boardptr->board_portbase = port;
4167
4168                   boardptr->board_chipbase = chip;
4169
4170                   sab82538_interrupt(irq, boardptr, regs);               
4171
4172                   break;
4173
4174                  
4175
4176                 case 0x40:      /* esccA */
4177
4178                   chip = cim->ci_chipbase;
4179
4180                   if(!chip)
4181
4182                     {
4183
4184                       printk(KERN_ALERT "aura mcs: missing cim.\n");
4185
4186                       break;
4187
4188                     }
4189
4190                   port = chip->c_portbase;
4191
4192                   boardptr->board_portbase = port;
4193
4194                   boardptr->board_chipbase = chip;
4195
4196                   sab82538_interrupt(irq, boardptr, regs);               
4197
4198                   break;
4199
4200                  
4201
4202                 case 0xc0:      /* esccB and esccA */
4203
4204                   chip = cim->ci_chipbase;
4205
4206                   if(!chip)
4207
4208                     {
4209
4210                       printk(KERN_ALERT "aura mcs: missing cim.\n");
4211
4212                       break;
4213
4214                     }
4215
4216                   port = chip->c_portbase;
4217
4218                   boardptr->board_portbase = port;
4219
4220                   boardptr->board_chipbase = chip;
4221
4222                   sab82538_interrupt(irq, boardptr, regs);               
4223
4224  
4225
4226                   chip = cim->ci_chipbase;
4227
4228                   if(!chip)
4229
4230                     {
4231
4232                       printk(KERN_ALERT "aura mcs: missing cim.\n");
4233
4234                       break;
4235
4236                     }
4237
4238                   chip = chip->next_by_cim;
4239
4240                   if(!chip)
4241
4242                     {
4243
4244                       printk(KERN_ALERT "aura mcs: missing 2nd cim.\n");
4245
4246                       break;
4247
4248                     }
4249
4250                   port = chip->c_portbase;
4251
4252                   boardptr->board_portbase = port;
4253
4254                   boardptr->board_chipbase = chip;
4255
4256                   sab82538_interrupt(irq, boardptr, regs);               
4257
4258                   break;
4259
4260                 }
4261
4262               boardptr->board_portbase = save_portlist;
4263
4264               boardptr->board_chipbase = save_chiplist;
4265
4266               cim = cim->next_by_mcs;
4267
4268             }
4269
4270         }
4271
4272     }
4273
4274 }
4275
4276  
4277
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
4284 routine.
4285
4286  
4287
4288 /Driver Unload Logic/
4289
4290  
4291
4292 The driver unload logic inverts the probe intialization logic.
4293
4294  
4295
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).
4299
4300  
4301
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.
4305
4306  
4307
4308 The PLX or AMCC interrupts to the Linux host are disabled on each board,
4309 and all interrupt handlers are freed.
4310
4311  
4312
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.
4324
4325  
4326
4327                                 /* cleanup module/free up virtual memory */
4328
4329                                 /* space*/
4330
4331 void cleanup_module(void)
4332
4333 {
4334
4335   SAB_BOARD *boardptr;
4336
4337   SAB_CHIP *chipptr;
4338
4339   SAB_PORT *portptr;
4340
4341   int intr_val;
4342
4343   extern void sab8253x_cleanup_ttydriver(void);
4344
4345  
4346
4347   printk(KERN_ALERT "auraXX50n: unloading AURAXX50 driver.\n");
4348
4349  
4350
4351   sab8253x_cleanup_ttydriver(); /* clean up tty */
4352
4353  
4354
4355                                 /* unallocate and turn off ints */
4356
4357   for(intr_val = 0; intr_val < NUMINTS; ++intr_val)
4358
4359     {
4360
4361       if((AuraBoardESCC2IrqRoot[intr_val] != NULL) ||
4362 (AuraBoardESCC8IrqRoot[intr_val] != NULL))
4363
4364         {
4365
4366           for(boardptr = AuraBoardESCC2IrqRoot[intr_val]; boardptr !=
4367 NULL; boardptr = boardptr->next_on_interrupt)
4368
4369             {
4370
4371               writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
4372
4373             }
4374
4375           for(boardptr = AuraBoardESCC8IrqRoot[intr_val]; boardptr !=
4376 NULL; boardptr = boardptr->next_on_interrupt)
4377
4378             {
4379
4380               writel(PLX_INT_OFF, &(boardptr->b_bridge->intr));
4381
4382             }
4383
4384  
4385
4386           free_irq(intr_val, &AuraBoardESCC2IrqRoot[intr_val]); /* free
4387 up board int
4388
4389                                                                  * note
4390 that if two boards
4391
4392                                                                  * share
4393 an int, two int
4394
4395                                                                  *
4396 handlers were registered
4397
4398                                                                  *
4399
4400                                                                  */
4401
4402         }
4403
4404     }
4405
4406  
4407
4408                                 /* disable chips and free board memory*/
4409
4410   while(AuraBoardRoot)
4411
4412     {
4413
4414       boardptr = AuraBoardRoot;
4415
4416       for(chipptr = boardptr->board_chipbase; chipptr != NULL; chipptr =
4417 chipptr->next_by_board)
4418
4419         {
4420
4421           (*chipptr->int_disable)(chipptr); /* make sure no ints can
4422 come int */
4423
4424         }
4425
4426       AuraBoardRoot = boardptr->nextboard;
4427
4428       if(boardptr->virtbaseaddress0)
4429
4430         {
4431
4432           DEBUGPRINT((KERN_ALERT
4433
4434                       "auraXX50n: unmapping virtual address %p.\n",
4435
4436                       (void*)boardptr->virtbaseaddress0));
4437
4438           iounmap((void*)boardptr->virtbaseaddress0);
4439
4440           boardptr->virtbaseaddress0 = 0;
4441
4442         }
4443
4444       if(boardptr->virtbaseaddress2)
4445
4446         {
4447
4448           DEBUGPRINT((KERN_ALERT
4449
4450                       "auraXX50n: unmapping virtual address %p.\n",
4451
4452                       (void*)boardptr->virtbaseaddress2));
4453
4454           iounmap((void*)boardptr->virtbaseaddress2);
4455
4456           boardptr->virtbaseaddress2 = 0;
4457
4458         }
4459
4460       kfree(boardptr);
4461
4462     }
4463
4464  
4465
4466   while(AuraChipRoot)           /* free chip memory */
4467
4468     {
4469
4470       chipptr = AuraChipRoot;
4471
4472       AuraChipRoot = chipptr->next;
4473
4474       kfree(chipptr);
4475
4476     }
4477
4478  
4479
4480   while(Sab8253xRoot)           /* free up network stuff */
4481
4482     {
4483
4484       SAB_PORT *priv;
4485
4486       priv = (SAB_PORT *)Sab8253xRoot->priv;
4487
4488       unregister_netdev(Sab8253xRoot);
4489
4490 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
4491
4492       kfree(Sab8253xRoot.name);
4493
4494 #endif
4495
4496       kfree(Sab8253xRoot);
4497
4498       Sab8253xRoot = priv->next_dev;
4499
4500     }
4501
4502  
4503
4504   while(AuraPortRoot)           /* free up port memory */
4505
4506     {
4507
4508       portptr = AuraPortRoot;
4509
4510       AuraPortRoot = portptr->next;
4511
4512       if(portptr->dcontrol2.receive)
4513
4514         {
4515
4516           kfree(portptr->dcontrol2.receive);
4517
4518         }
4519
4520       if(portptr->dcontrol2.transmit)
4521
4522         {
4523
4524           kfree(portptr->dcontrol2.transmit);
4525
4526         }
4527
4528       kfree(portptr);
4529
4530     }
4531
4532 }
4533
4534  
4535
4536 _Design Summary_
4537
4538  
4539
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.
4560
4561  
4562