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 */
37static 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
59static 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
72static 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
81static 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
86static 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
91static 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
115static 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
125static 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
157static 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
198static 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
211static 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
224static void bpck6_release_proto(PIA *pi)
225{
226	kfree((void *)(pi->private));
227}
228
229static 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
248static 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
257static void __exit bpck6_exit(void)
258{
259	paride_unregister(&bpck6);
260}
261
262MODULE_LICENSE("GPL");
263MODULE_AUTHOR("Micro Solutions Inc.");
264MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
265module_param(verbose, bool, 0644);
266module_init(bpck6_init)
267module_exit(bpck6_exit)
268