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