diff options
Diffstat (limited to 'drivers/block/paride/bpck6.c')
-rw-r--r-- | drivers/block/paride/bpck6.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c new file mode 100644 index 000000000000..08d858ad64db --- /dev/null +++ b/drivers/block/paride/bpck6.c | |||
@@ -0,0 +1,282 @@ | |||
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) | ||