4    Copyright (C) 1993,1994 Jon Tombs.
 
   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.
 
  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.
 
  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
 
  20    Modified for distribution with ftape source. 21 June 94, SJL.
 
  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.
 
  30    - You can not use DMA Channels 5 or 7.
 
  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
 
  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.
 
  46  * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/fc-10.c,v $
 
  48  * $Date: 1997/10/05 19:18:04 $
 
  50  *      This file contains code for the CMS FC-10/FC-20 card.
 
  54 #include <linux/ftape.h>
 
  55 #include "../lowlevel/ftape-tracing.h"
 
  56 #include "../lowlevel/fdc-io.h"
 
  57 #include "../lowlevel/fc-10.h"
 
  59 static __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
 
  65 static __u16 fc10_ports[] = {
 
  66         0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370
 
  72         __u8 cardConfig = 0x00;
 
  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.
 
  81                 TRACE_ABORT(0, ft_t_err,
 
  82 "Error: The FC-10/20 must be set to use DMA channels 1, 2, or 3!");
 
  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.
 
  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");
 
  92         /*  Clear state machine ???
 
  94         for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
 
  95                 inb(ft_fdc_base + inbs_magic[i]);
 
  97         outb(0x0, ft_fdc_base);
 
 100         if (x == 0x13 || x == 0x93) {
 
 101                 for (i = 1; i < 8; i++) {
 
 102                         if (inb(ft_fdc_base + i) != x) {
 
 110         outb(0x8, ft_fdc_base);
 
 112         for (i = 0; i < 8; i++) {
 
 113                 if (inb(ft_fdc_base + i) != 0x0) {
 
 117         outb(0x10, ft_fdc_base);
 
 119         for (i = 0; i < 8; i++) {
 
 120                 if (inb(ft_fdc_base + i) != 0xff) {
 
 125         /*  Okay, we found a FC-10 card ! ???
 
 129         /*  Clear state machine again ???
 
 131         for (i = 0; i < NR_ITEMS(inbs_magic); i++) {
 
 132                 inb(ft_fdc_base + inbs_magic[i]);
 
 135         for (i = 0; i < NR_ITEMS(fc10_ports); i++)
 
 136                 if (ft_fdc_base == fc10_ports[i])
 
 138         if (cardConfig == 0) {
 
 139                 TRACE_EXIT 0;   /* Invalid I/O Port */
 
 141         /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */
 
 143                 cardConfig |= ft_fdc_irq << 3;
 
 145                 cardConfig |= 2 << 3;
 
 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] */
 
 155         outb(FDC_DMA_MODE /* 8 */, fdc.dor);
 
 156         outb(FDC_DMA_MODE /* 8 */, fdc.dor);
 
 159         /*************************************
 
 161          * cH: why the hell should this be necessary? This is done 
 
 164          *************************************/
 
 165         /*  Initialize fdc, select drive B:
 
 167         outb(FDC_DMA_MODE, fdc.dor);    /* assert reset, dma & irq enabled */
 
 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;