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 /*
15    This is Ken's linux wrapper for the PPC library
16    Version 1.0.0 is the backpack driver for which source is not available
17    Version 2.0.0 is the first to have source released
18    Version 2.0.1 is the "Cox-ified" source code
19    Version 2.0.2 - fixed version string usage, and made ppc functions static
20 */
21 
22 
23 #define BACKPACK_VERSION "2.0.2"
24 
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/types.h>
30 #include <asm/io.h>
31 #include <linux/parport.h>
32 
33 #include "ppc6lnx.c"
34 #include "paride.h"
35 
36 /* PARAMETERS */
37 static bool verbose; /* set this to 1 to see debugging messages and whatnot */
38 
39 
40 #define PPCSTRUCT(pi) ((Interface *)(pi->private))
41 
42 /****************************************************************/
43 /*
44  ATAPI CDROM DRIVE REGISTERS
45 */
46 #define ATAPI_DATA       0      /* data port                  */
47 #define ATAPI_ERROR      1      /* error register (read)      */
48 #define ATAPI_FEATURES   1      /* feature register (write)   */
49 #define ATAPI_INT_REASON 2      /* interrupt reason register  */
50 #define ATAPI_COUNT_LOW  4      /* byte count register (low)  */
51 #define ATAPI_COUNT_HIGH 5      /* byte count register (high) */
52 #define ATAPI_DRIVE_SEL  6      /* drive select register      */
53 #define ATAPI_STATUS     7      /* status port (read)         */
54 #define ATAPI_COMMAND    7      /* command port (write)       */
55 #define ATAPI_ALT_STATUS 0x0e /* alternate status reg (read) */
56 #define ATAPI_DEVICE_CONTROL 0x0e /* device control (write)   */
57 /****************************************************************/
58 
bpck6_read_regr(PIA * pi,int cont,int reg)59 static int bpck6_read_regr(PIA *pi, int cont, int reg)
60 {
61 	unsigned int out;
62 
63 	/* check for bad settings */
64 	if (reg<0 || reg>7 || cont<0 || cont>2)
65 	{
66 		return(-1);
67 	}
68 	out=ppc6_rd_port(PPCSTRUCT(pi),cont?reg|8:reg);
69 	return(out);
70 }
71 
bpck6_write_regr(PIA * pi,int cont,int reg,int val)72 static void bpck6_write_regr(PIA *pi, int cont, int reg, int val)
73 {
74 	/* check for bad settings */
75 	if (reg>=0 && reg<=7 && cont>=0 && cont<=1)
76 	{
77 		ppc6_wr_port(PPCSTRUCT(pi),cont?reg|8:reg,(u8)val);
78 	}
79 }
80 
bpck6_write_block(PIA * pi,char * buf,int len)81 static void bpck6_write_block( PIA *pi, char * buf, int len )
82 {
83 	ppc6_wr_port16_blk(PPCSTRUCT(pi),ATAPI_DATA,buf,(u32)len>>1);
84 }
85 
bpck6_read_block(PIA * pi,char * buf,int len)86 static void bpck6_read_block( PIA *pi, char * buf, int len )
87 {
88 	ppc6_rd_port16_blk(PPCSTRUCT(pi),ATAPI_DATA,buf,(u32)len>>1);
89 }
90 
bpck6_connect(PIA * pi)91 static void bpck6_connect ( PIA *pi  )
92 {
93 	if(verbose)
94 	{
95 		printk(KERN_DEBUG "connect\n");
96 	}
97 
98 	if(pi->mode >=2)
99   	{
100 		PPCSTRUCT(pi)->mode=4+pi->mode-2;
101 	}
102 	else if(pi->mode==1)
103 	{
104 		PPCSTRUCT(pi)->mode=3;
105 	}
106 	else
107 	{
108 		PPCSTRUCT(pi)->mode=1;
109 	}
110 
111 	ppc6_open(PPCSTRUCT(pi));
112 	ppc6_wr_extout(PPCSTRUCT(pi),0x3);
113 }
114 
bpck6_disconnect(PIA * pi)115 static void bpck6_disconnect ( PIA *pi )
116 {
117 	if(verbose)
118 	{
119 		printk("disconnect\n");
120 	}
121 	ppc6_wr_extout(PPCSTRUCT(pi),0x0);
122 	ppc6_close(PPCSTRUCT(pi));
123 }
124 
bpck6_test_port(PIA * pi)125 static int bpck6_test_port ( PIA *pi )   /* check for 8-bit port */
126 {
127 	if(verbose)
128 	{
129 		printk(KERN_DEBUG "PARPORT indicates modes=%x for lp=0x%lx\n",
130                		((struct pardevice*)(pi->pardev))->port->modes,
131 			((struct pardevice *)(pi->pardev))->port->base);
132 	}
133 
134 	/*copy over duplicate stuff.. initialize state info*/
135 	PPCSTRUCT(pi)->ppc_id=pi->unit;
136 	PPCSTRUCT(pi)->lpt_addr=pi->port;
137 
138 	/* look at the parport device to see if what modes we can use */
139 	if(((struct pardevice *)(pi->pardev))->port->modes &
140 		(PARPORT_MODE_EPP)
141           )
142 	{
143 		return 5; /* Can do EPP*/
144 	}
145 	else if(((struct pardevice *)(pi->pardev))->port->modes &
146 			(PARPORT_MODE_TRISTATE)
147                )
148 	{
149 		return 2;
150 	}
151 	else /*Just flat SPP*/
152 	{
153 		return 1;
154 	}
155 }
156 
bpck6_probe_unit(PIA * pi)157 static int bpck6_probe_unit ( PIA *pi )
158 {
159 	int out;
160 
161 	if(verbose)
162 	{
163 		printk(KERN_DEBUG "PROBE UNIT %x on port:%x\n",pi->unit,pi->port);
164 	}
165 
166 	/*SET PPC UNIT NUMBER*/
167 	PPCSTRUCT(pi)->ppc_id=pi->unit;
168 
169 	/*LOWER DOWN TO UNIDIRECTIONAL*/
170 	PPCSTRUCT(pi)->mode=1;
171 
172 	out=ppc6_open(PPCSTRUCT(pi));
173 
174 	if(verbose)
175 	{
176 		printk(KERN_DEBUG "ppc_open returned %2x\n",out);
177 	}
178 
179   	if(out)
180  	{
181 		ppc6_close(PPCSTRUCT(pi));
182 		if(verbose)
183 		{
184 			printk(KERN_DEBUG "leaving probe\n");
185 		}
186                return(1);
187 	}
188   	else
189   	{
190 		if(verbose)
191 		{
192 			printk(KERN_DEBUG "Failed open\n");
193 		}
194     		return(0);
195   	}
196 }
197 
bpck6_log_adapter(PIA * pi,char * scratch,int verbose)198 static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose )
199 {
200 	char *mode_string[5]=
201 		{"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
202 
203 	printk("%s: BACKPACK Protocol Driver V"BACKPACK_VERSION"\n",pi->device);
204 	printk("%s: Copyright 2001 by Micro Solutions, Inc., DeKalb IL.\n",pi->device);
205 	printk("%s: BACKPACK %s, Micro Solutions BACKPACK Drive at 0x%x\n",
206 		pi->device,BACKPACK_VERSION,pi->port);
207 	printk("%s: Unit: %d Mode:%d (%s) Delay %d\n",pi->device,
208 		pi->unit,pi->mode,mode_string[pi->mode],pi->delay);
209 }
210 
bpck6_init_proto(PIA * pi)211 static int bpck6_init_proto(PIA *pi)
212 {
213 	Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL);
214 
215 	if (p) {
216 		pi->private = (unsigned long)p;
217 		return 0;
218 	}
219 
220 	printk(KERN_ERR "%s: ERROR COULDN'T ALLOCATE MEMORY\n", pi->device);
221 	return -1;
222 }
223 
bpck6_release_proto(PIA * pi)224 static void bpck6_release_proto(PIA *pi)
225 {
226 	kfree((void *)(pi->private));
227 }
228 
229 static struct pi_protocol bpck6 = {
230 	.owner		= THIS_MODULE,
231 	.name		= "bpck6",
232 	.max_mode	= 5,
233 	.epp_first	= 2, /* 2-5 use epp (need 8 ports) */
234 	.max_units	= 255,
235 	.write_regr	= bpck6_write_regr,
236 	.read_regr	= bpck6_read_regr,
237 	.write_block	= bpck6_write_block,
238 	.read_block	= bpck6_read_block,
239 	.connect	= bpck6_connect,
240 	.disconnect	= bpck6_disconnect,
241 	.test_port	= bpck6_test_port,
242 	.probe_unit	= bpck6_probe_unit,
243 	.log_adapter	= bpck6_log_adapter,
244 	.init_proto	= bpck6_init_proto,
245 	.release_proto	= bpck6_release_proto,
246 };
247 
bpck6_init(void)248 static int __init bpck6_init(void)
249 {
250 	printk(KERN_INFO "bpck6: BACKPACK Protocol Driver V"BACKPACK_VERSION"\n");
251 	printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n");
252 	if(verbose)
253 		printk(KERN_DEBUG "bpck6: verbose debug enabled.\n");
254 	return paride_register(&bpck6);
255 }
256 
bpck6_exit(void)257 static void __exit bpck6_exit(void)
258 {
259 	paride_unregister(&bpck6);
260 }
261 
262 MODULE_LICENSE("GPL");
263 MODULE_AUTHOR("Micro Solutions Inc.");
264 MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
265 module_param(verbose, bool, 0644);
266 module_init(bpck6_init)
267 module_exit(bpck6_exit)
268