1 /* 2 backpack.c (c) 2001 Micro Solutions Inc. 3 Released under the terms of the GNU General Public license 4 5 backpack.c is a low-level protocol driver for the Micro Solutions 6 "BACKPACK" parallel port IDE adapter 7 (Works on Series 6 drives) 8 9 Written by: Ken Hahn (linux-dev@micro-solutions.com) 10 Clive Turvey (linux-dev@micro-solutions.com) 11 12 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/kernel.h> 17 #include <linux/types.h> 18 #include <linux/parport.h> 19 #include "pata_parport.h" 20 #include "ppc6lnx.c" 21 22 static int bpck6_read_regr(struct pi_adapter *pi, int cont, int reg) 23 { 24 u8 port = cont ? reg | 8 : reg; 25 26 ppc6_send_cmd(pi, port | ACCESS_PORT | ACCESS_READ); 27 return ppc6_rd_data_byte(pi); 28 } 29 30 static void bpck6_write_regr(struct pi_adapter *pi, int cont, int reg, int val) 31 { 32 u8 port = cont ? reg | 8 : reg; 33 34 ppc6_send_cmd(pi, port | ACCESS_PORT | ACCESS_WRITE); 35 ppc6_wr_data_byte(pi, val); 36 } 37 38 static void bpck6_write_block(struct pi_adapter *pi, char *buf, int len) 39 { 40 ppc6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE); 41 ppc6_wr_data_byte(pi, (u8)len); 42 ppc6_wr_data_byte(pi, (u8)(len >> 8)); 43 ppc6_wr_data_byte(pi, 0); 44 45 ppc6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK); 46 ppc6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_WRITE); 47 ppc6_wr_data_blk(pi, buf, len); 48 ppc6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK); 49 } 50 51 static void bpck6_read_block(struct pi_adapter *pi, char *buf, int len) 52 { 53 ppc6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE); 54 ppc6_wr_data_byte(pi, (u8)len); 55 ppc6_wr_data_byte(pi, (u8)(len >> 8)); 56 ppc6_wr_data_byte(pi, 0); 57 58 ppc6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK); 59 ppc6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_READ); 60 ppc6_rd_data_blk(pi, buf, len); 61 ppc6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK); 62 } 63 64 static void bpck6_connect(struct pi_adapter *pi) 65 { 66 dev_dbg(&pi->dev, "connect\n"); 67 68 ppc6_open(pi); 69 ppc6_wr_extout(pi, 0x3); 70 } 71 72 static void bpck6_disconnect(struct pi_adapter *pi) 73 { 74 dev_dbg(&pi->dev, "disconnect\n"); 75 ppc6_wr_extout(pi, 0x0); 76 ppc6_deselect(pi); 77 } 78 79 static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */ 80 { 81 dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n", 82 pi->pardev->port->modes, pi->pardev->port->base); 83 84 /* look at the parport device to see what modes we can use */ 85 if (pi->pardev->port->modes & PARPORT_MODE_EPP) 86 return 5; /* Can do EPP */ 87 if (pi->pardev->port->modes & PARPORT_MODE_TRISTATE) 88 return 2; 89 return 1; /* Just flat SPP */ 90 } 91 92 static int bpck6_probe_unit(struct pi_adapter *pi) 93 { 94 int out, saved_mode; 95 96 dev_dbg(&pi->dev, "PROBE UNIT %x on port:%x\n", pi->unit, pi->port); 97 98 saved_mode = pi->mode; 99 /*LOWER DOWN TO UNIDIRECTIONAL*/ 100 pi->mode = 0; 101 102 out = ppc6_open(pi); 103 104 dev_dbg(&pi->dev, "ppc_open returned %2x\n", out); 105 106 if(out) 107 { 108 ppc6_deselect(pi); 109 dev_dbg(&pi->dev, "leaving probe\n"); 110 pi->mode = saved_mode; 111 return(1); 112 } 113 else 114 { 115 dev_dbg(&pi->dev, "Failed open\n"); 116 pi->mode = saved_mode; 117 return(0); 118 } 119 } 120 121 static void bpck6_log_adapter(struct pi_adapter *pi) 122 { 123 char *mode_string[5]= 124 {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"}; 125 126 dev_info(&pi->dev, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n", 127 pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay); 128 } 129 130 static struct pi_protocol bpck6 = { 131 .owner = THIS_MODULE, 132 .name = "bpck6", 133 .max_mode = 5, 134 .epp_first = 2, /* 2-5 use epp (need 8 ports) */ 135 .max_units = 255, 136 .write_regr = bpck6_write_regr, 137 .read_regr = bpck6_read_regr, 138 .write_block = bpck6_write_block, 139 .read_block = bpck6_read_block, 140 .connect = bpck6_connect, 141 .disconnect = bpck6_disconnect, 142 .test_port = bpck6_test_port, 143 .probe_unit = bpck6_probe_unit, 144 .log_adapter = bpck6_log_adapter, 145 }; 146 147 MODULE_LICENSE("GPL"); 148 MODULE_AUTHOR("Micro Solutions Inc."); 149 MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE"); 150 module_pata_parport_driver(bpck6); 151