1 /* Yo, Emacs! we're -*- Linux-C -*- 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 independant 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 * 41 * This file contains code for the CMS FC-10/FC-20 card. 42 */ 43 44 #include <linux/module.h> 45 #include <linux/ftape.h> 46 #include <asm/io.h> 47 48 #include "tracing.h" 49 #include "fdc-io.h" 50 #include "fc-10.h" 51 52 #ifdef PROBE_FC10 53 54 /* This code will only work if the FC-10 (or FC-20) is set to 55 * use DMA channels 1, 2, or 3. DMA channels 5 and 7 seem to be 56 * initialized by the same command as channels 1 and 3, respectively. 57 */ 58 #if (FDC_DMA > 3) 59 #error : The FC-10/20 must be set to use DMA channels 1, 2, or 3! 60 #endif 61 62 /* Only allow the FC-10/20 to use IRQ 3-7, or 9. Note that CMS's program 63 * only accepts IRQ's 2-7, but in linux, IRQ 2 is the same as IRQ 9. 64 */ 65 #if (FDC_IRQ < 3 || FDC_IRQ == 8 || FDC_IRQ > 9) 66 #error : The FC-10/20 must be set to use IRQ levels 3 - 7, or 9! 67 #error : Note IRQ 9 is the same as IRQ 2 68 #endif 69 70 unsigned short inbs_magic[] = { 71 0x3, 0x3, 0x0, 0x4, 0x7, 0x2, 0x5, 0x3, 0x1, 0x4, 72 0x3, 0x5, 0x2, 0x0, 0x3, 0x7, 0x4, 0x2, 73 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 74 }; 75 76 unsigned short fc10_ports[] = { 77 0x180, 0x210, 0x2A0, 0x300, 0x330, 0x340, 0x370 78 }; 79 80 int fc10_enable(void) /* */ 81 { 82 int i; 83 byte cardConfig = 0x00; 84 byte x; 85 86 /* Clear state machine ??? 87 */ 88 for (i = 0; i < NR_ITEMS(inbs_magic); i++) { 89 inb(FDC_BASE + inbs_magic[i]); 90 } 91 outb(0x0, FDC_BASE); 92 93 x = inb(FDC_BASE); 94 if (x == 0x13 || x == 0x93) { 95 for (i = 1; i < 8; i++) { 96 if (inb(FDC_BASE + i) != x) { 97 return 0; 98 } 99 } 100 } else { 101 return 0; 102 } 103 104 outb(0x8, FDC_BASE); 105 106 for (i = 0; i < 8; i++) { 107 if (inb(FDC_BASE + i) != 0x0) { 108 return 0; 109 } 110 } 111 outb(0x10, FDC_BASE); 112 113 for (i = 0; i < 8; i++) { 114 if (inb(FDC_BASE + i) != 0xff) { 115 return 0; 116 } 117 } 118 119 /* Okay, we found a FC-10 card ! ??? 120 */ 121 outb(0x0, fdc.ccr); 122 123 /* Clear state machine again ??? 124 */ 125 for (i = 0; i < NR_ITEMS(inbs_magic); i++) { 126 inb(FDC_BASE + inbs_magic[i]); 127 } 128 /* Send io port */ 129 for (i = 0; i < NR_ITEMS(fc10_ports); i++) 130 if (FDC_BASE == fc10_ports[i]) 131 cardConfig = i + 1; 132 if (cardConfig == 0) 133 return 0; /* Invalid I/O Port */ 134 /* and IRQ - If using IRQ 9, tell the FC card it is actually IRQ 2 */ 135 if (FDC_IRQ != 9) 136 cardConfig |= FDC_IRQ << 3; 137 else 138 cardConfig |= 2 << 3; 139 140 /* and finally DMA Channel */ 141 cardConfig |= FDC_DMA << 6; 142 outb(cardConfig, FDC_BASE); /* DMA [2 bits]/IRQ [3 bits]/BASE [3 bits] */ 143 144 /* Enable FC-10 ??? 145 */ 146 outb(0, fdc.ccr); 147 outb(0, FDC_BASE + 0x6); 148 outb(8, fdc.dor); 149 outb(8, fdc.dor); 150 outb(1, FDC_BASE + 0x6); 151 152 /* Initialize fdc, select drive B: 153 */ 154 outb(0x08, fdc.dor); /* assert reset, dma & irq enabled */ 155 outb(0x0c, fdc.dor); /* release reset */ 156 outb(0x2d, fdc.dor); /* select drive 1 */ 157 158 return (x == 0x93) ? 2 : 1; 159 } 160 161 #endif /* CMS_FC10_CONTROLLER */