File: /usr/src/linux/drivers/char/ftape/lowlevel/fc-10.c

1     /*
2      *
3     
4        Copyright (C) 1993,1994 Jon Tombs.
5     
6        This program is distributed in the hope that it will be useful,
7        but WITHOUT ANY WARRANTY; without even the implied warranty of
8        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9        GNU General Public License for more details.
10     
11        The entire guts of this program was written by dosemu, modified to
12        record reads and writes to the ports in the 0x180-0x188 address space,
13        while running the CMS program TAPE.EXE V2.0.5 supplied with the drive.
14     
15        Modified to use an array of addresses and generally cleaned up (made
16        much shorter) 4 June 94, dosemu isn't that good at writing short code it
17        would seem :-). Made independent of 0x180, but I doubt it will work
18        at any other address.
19     
20        Modified for distribution with ftape source. 21 June 94, SJL.
21     
22        Modifications on 20 October 95, by Daniel Cohen (catman@wpi.edu):
23        Modified to support different DMA, IRQ, and IO Ports.  Borland's
24        Turbo Debugger in virtual 8086 mode (TD386.EXE with hardware breakpoints
25        provided by the TDH386.SYS Device Driver) was used on the CMS program
26        TAPE V4.0.5.  I set breakpoints on I/O to ports 0x180-0x187.  Note that
27        CMS's program will not successfully configure the tape drive if you set
28        breakpoints on IO Reads, but you can set them on IO Writes without problems.
29        Known problems:
30        - You can not use DMA Channels 5 or 7.
31     
32        Modification on 29 January 96, by Daniel Cohen (catman@wpi.edu):
33        Modified to only accept IRQs 3 - 7, or 9.  Since we can only send a 3 bit
34        number representing the IRQ to the card, special handling is required when
35        IRQ 9 is selected.  IRQ 2 and 9 are the same, and we should request IRQ 9
36        from the kernel while telling the card to use IRQ 2.  Thanks to Greg
37        Crider (gcrider@iclnet.org) for finding and locating this bug, as well as
38        testing the patch.
39     
40        Modification on 11 December 96, by Claus Heine (claus@momo.math.rwth-aachen.de):
41        Modified a little to use variahle ft_fdc_base, ft_fdc_irq, ft_fdc_dma 
42        instead of preprocessor symbols. Thus we can compile this into the module
43        or kernel and let the user specify the options as command line arguments.
44     
45      *
46      * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $
47      * $Revision: 1.2 $
48      * $Date: 1997/10/05 19:18:04 $
49      *
50      *      This file contains code for the CMS FC-10/FC-20 card.
51      */
52     
53     #include <asm/io.h>
54     #include <linux/ftape.h>
55     #include "../lowlevel/ftape-tracing.h"
56     #include "../lowlevel/fdc-io.h"
57     #include "../lowlevel/fc-10.h"
58     
59     __u16 inbs_magic[] = {
60     	0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4,
61     	0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2,
62     	0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
63     };
64     
65     __u16 fc10_ports[] = {
66     	0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370
67     };
68     
69     int fc10_enable(void)
70     {
71     	int i;
72     	__u8 cardConfig = 0x00;
73     	__u8 x;
74     	TRACE_FUN(ft_t_flow);
75     
76     /*  This code will only work if the FC-10 (or FC-20) is set to
77      *  use DMA channels 1, 2, or 3.  DMA channels 5 and 7 seem to be 
78      *  initialized by the same command as channels 1 and 3, respectively.
79      */
80     	if (ft_fdc_dma > 3) {
81     		TRACE_ABORT(0, ft_t_err,
82     "Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!");
83     	}
84     /*  Only allow the FC-10/20 to use IRQ 3-7, or 9.  Note that CMS's program
85      *  only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9.
86      */
87     	if (ft_fdc_irq < 3 || ft_fdc_irq == 8 || ft_fdc_irq > 9) {
88     		TRACE_ABORT(0, ft_t_err, 
89     "Error: The FC-10/20 must be set to use IRQ levels 3 - 7, or 9!\n"
90     KERN_INFO "Note: IRQ 9 is the same as IRQ 2");
91     	}
92     	/*  Clear state machine ???
93     	 */
94     	for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
95     		inb(ft_fdc_base + inbs_magic[i]);
96     	}
97     	outb(0x0, ft_fdc_base);
98     
99     	x = inb(ft_fdc_base);
100     	if (x == 0x13 || x == 0x93) {
101     		for (i = 1; i < 8; i++) {
102     			if (inb(ft_fdc_base + i) != x) {
103     				TRACE_EXIT 0;
104     			}
105     		}
106     	} else {
107     		TRACE_EXIT 0;
108     	}
109     
110     	outb(0x8, ft_fdc_base);
111     
112     	for (i = 0; i < 8; i++) {
113     		if (inb(ft_fdc_base + i) != 0x0) {
114     			TRACE_EXIT 0;
115     		}
116     	}
117     	outb(0x10, ft_fdc_base);
118     
119     	for (i = 0; i < 8; i++) {
120     		if (inb(ft_fdc_base + i) != 0xff) {
121     			TRACE_EXIT 0;
122     		}
123     	}
124     
125     	/*  Okay, we found a FC-10 card ! ???
126     	 */
127     	outb(0x0, fdc.ccr);
128     
129     	/*  Clear state machine again ???
130     	 */
131     	for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
132     		inb(ft_fdc_base + inbs_magic[i]);
133     	}
134     	/* Send io port */
135     	for (i = 0; i < NR_ITEMS(fc10_ports); i++)
136     		if (ft_fdc_base == fc10_ports[i])
137     			cardConfig = i + 1;
138     	if (cardConfig == 0) {
139     		TRACE_EXIT 0;	/* Invalid I/O Port */
140     	}
141     	/* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */
142     	if (ft_fdc_irq != 9)
143     		cardConfig |= ft_fdc_irq << 3;
144     	else
145     		cardConfig |= 2 << 3;
146     
147     	/* and finally DMA Channel */
148     	cardConfig |= ft_fdc_dma << 6;
149     	outb(cardConfig, ft_fdc_base);	/* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */
150     
151     	/*  Enable FC-10 ???
152     	 */
153     	outb(0, fdc.ccr);
154     	outb(0, fdc.dor2);
155     	outb(FDC_DMA_MODE /* 8 */, fdc.dor);
156     	outb(FDC_DMA_MODE /* 8 */, fdc.dor);
157     	outb(1, fdc.dor2);
158     
159     	/*************************************
160     	 *
161     	 * cH: why the hell should this be necessary? This is done 
162     	 *     by fdc_reset()!!!
163     	 *
164     	 *************************************/
165     	/*  Initialize fdc, select drive B:
166     	 */
167     	outb(FDC_DMA_MODE, fdc.dor);	/* assert reset, dma & irq enabled */
168     	/*       0x08    */
169     	outb(FDC_DMA_MODE|FDC_RESET_NOT, fdc.dor);	/* release reset */
170     	/*       0x08    |   0x04   = 0x0c */
171     	outb(FDC_DMA_MODE|FDC_RESET_NOT|FDC_MOTOR_1|FTAPE_SEL_B, fdc.dor);
172     	/*       0x08    |   0x04      |  0x20     |  0x01  = 0x2d */    
173     	/* select drive 1 */ /* why not drive 0 ???? */
174     	TRACE_EXIT (x == 0x93) ? 2 : 1;
175     }
176