1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (c) 1997-8 Grant R. Guenther <grant@torque.net> 4 * 5 * aten.c is a low-level protocol driver for the ATEN EH-100 6 * parallel port adapter. The EH-100 supports 4-bit and 8-bit 7 * modes only. There is also an EH-132 which supports EPP mode 8 * transfers. The EH-132 is not yet supported. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/delay.h> 14 #include <linux/kernel.h> 15 #include <linux/wait.h> 16 #include <linux/types.h> 17 #include <asm/io.h> 18 #include "pata_parport.h" 19 20 #define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) 21 22 /* 23 * cont = 0 - access the IDE register file 24 * cont = 1 - access the IDE command set 25 */ 26 static int cont_map[2] = { 0x08, 0x20 }; 27 28 static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val) 29 { 30 int r = regr + cont_map[cont] + 0x80; 31 32 w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc); 33 } 34 35 static int aten_read_regr(struct pi_adapter *pi, int cont, int regr) 36 { 37 int a, b, r; 38 39 r = regr + cont_map[cont] + 0x40; 40 41 switch (pi->mode) { 42 43 case 0: 44 w0(r); w2(0xe); w2(6); 45 w2(7); w2(6); w2(0); 46 a = r1(); w0(0x10); b = r1(); w2(0xc); 47 return j44(a,b); 48 49 case 1: 50 r |= 0x10; 51 w0(r); w2(0xe); w2(6); w0(0xff); 52 w2(0x27); w2(0x26); w2(0x20); 53 a = r0(); 54 w2(0x26); w2(0xc); 55 return a; 56 } 57 return -1; 58 } 59 60 static void aten_read_block(struct pi_adapter *pi, char *buf, int count) 61 { 62 int k, a, b, c, d; 63 64 switch (pi->mode) { 65 66 case 0: 67 w0(0x48); w2(0xe); w2(6); 68 for (k = 0; k < count / 2; k++) { 69 w2(7); w2(6); w2(2); 70 a = r1(); w0(0x58); b = r1(); 71 w2(0); d = r1(); w0(0x48); c = r1(); 72 buf[2 * k] = j44(c, d); 73 buf[2 * k + 1] = j44(a, b); 74 } 75 w2(0xc); 76 break; 77 78 case 1: 79 w0(0x58); w2(0xe); w2(6); 80 for (k = 0; k < count / 2; k++) { 81 w2(0x27); w2(0x26); w2(0x22); 82 a = r0(); w2(0x20); b = r0(); 83 buf[2 * k] = b; 84 buf[2 * k + 1] = a; 85 } 86 w2(0x26); w2(0xc); 87 break; 88 } 89 } 90 91 static void aten_write_block(struct pi_adapter *pi, char *buf, int count) 92 { 93 int k; 94 95 w0(0x88); w2(0xe); w2(6); 96 for (k = 0; k < count / 2; k++) { 97 w0(buf[2 * k + 1]); w2(0xe); w2(6); 98 w0(buf[2 * k]); w2(7); w2(6); 99 } 100 w2(0xc); 101 } 102 103 static void aten_connect(struct pi_adapter *pi) 104 { 105 pi->saved_r0 = r0(); 106 pi->saved_r2 = r2(); 107 w2(0xc); 108 } 109 110 static void aten_disconnect(struct pi_adapter *pi) 111 { 112 w0(pi->saved_r0); 113 w2(pi->saved_r2); 114 } 115 116 static void aten_log_adapter(struct pi_adapter *pi) 117 { 118 char *mode_string[2] = { "4-bit", "8-bit" }; 119 120 dev_info(&pi->dev, 121 "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n", 122 pi->port, pi->mode, mode_string[pi->mode], pi->delay); 123 } 124 125 static struct pi_protocol aten = { 126 .owner = THIS_MODULE, 127 .name = "aten", 128 .max_mode = 2, 129 .epp_first = 2, 130 .default_delay = 1, 131 .max_units = 1, 132 .write_regr = aten_write_regr, 133 .read_regr = aten_read_regr, 134 .write_block = aten_write_block, 135 .read_block = aten_read_block, 136 .connect = aten_connect, 137 .disconnect = aten_disconnect, 138 .log_adapter = aten_log_adapter, 139 }; 140 141 MODULE_LICENSE("GPL"); 142 MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>"); 143 MODULE_DESCRIPTION("ATEN EH-100 parallel port IDE adapter protocol driver"); 144 module_pata_parport_driver(aten); 145