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