This source file includes following definitions.
- out_p
- in_p
- ppa_d_pulse
- ppa_disconnect
- ppa_c_pulse
- ppa_connect
- ppa_do_reset
- ppa_select
- ppa_wait
- ppa_init
- ppa_start
- ppa_completion
- ppa_command
- ppa_queuecommand
- ppa_detect
- ppa_biosparam
- ppa_abort
- ppa_reset
- ppa_info
- ppa_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #define PPA_VERSION "0.20"
35
36
37
38
39
40 static int ppa_base = 0x378;
41 static int ppa_speed_high = 1;
42 static int ppa_speed_low = 6;
43 static int ppa_call_sched = 1;
44 static int ppa_nybble = 0;
45
46
47 #define PPA_CAN_QUEUE 1
48 #define PPA_SELECT_TMO 5000
49 #define PPA_SPIN_TMO 5000000
50 #define PPA_SECTOR_SIZE 512
51
52 #include <unistd.h>
53 #include <linux/module.h>
54 #include <linux/kernel.h>
55 #include <linux/ioport.h>
56 #include <linux/delay.h>
57 #include <linux/blk.h>
58 #include <linux/proc_fs.h>
59 #include <linux/stat.h>
60 #include <asm/io.h>
61 #include "sd.h"
62 #include "hosts.h"
63 #include "ppa.h"
64
65 struct proc_dir_entry proc_scsi_ppa =
66 { PROC_SCSI_PPA, 3, "ppa", S_IFDIR|S_IRUGO|S_IXUGO, 2 };
67
68 static int ppa_abort_flag = 0;
69 static int ppa_error_code = DID_OK;
70 static char ppa_info_string[132];
71 static Scsi_Cmnd *ppa_current = 0;
72 static void (*ppa_done) (Scsi_Cmnd *);
73 static int ppa_busy = 0;
74 static int ppa_port_delay;
75
76
77 void out_p( short port, char byte)
78
79 { outb(byte,ppa_base+port);
80 udelay(ppa_port_delay);
81 }
82
83 char in_p( short port)
84
85 { return inb(ppa_base+port);
86 udelay(ppa_port_delay);
87 }
88
89 void ppa_d_pulse( char b )
90
91 { out_p(0,b);
92 out_p(2,0xc); out_p(2,0xe); out_p(2,0xc); out_p(2,0x4); out_p(2,0xc);
93 }
94
95 void ppa_disconnect( void )
96
97 { ppa_d_pulse(0);
98 ppa_d_pulse(0x3c);
99 ppa_d_pulse(0x20);
100 ppa_d_pulse(0xf);
101 }
102
103 void ppa_c_pulse( char b )
104
105 { out_p(0,b);
106 out_p(2,0x4); out_p(2,0x6); out_p(2,0x4); out_p(2,0xc);
107 }
108
109 void ppa_connect( void )
110
111 { ppa_c_pulse(0);
112 ppa_c_pulse(0x3c);
113 ppa_c_pulse(0x20);
114 ppa_c_pulse(0x8f);
115 }
116
117 void ppa_do_reset( void )
118
119 { out_p(2,0);
120 udelay(100);
121 }
122
123 char ppa_select( int initiator, int target )
124
125 { char r;
126 int k;
127
128 r = in_p(1);
129 out_p(0,(1<<target)); out_p(2,0xe); out_p(2,0xc);
130 out_p(0,(1<<initiator)); out_p(2,0x8);
131
132 k = 0;
133 while ( !(r = (in_p(1) & 0xf0)) && (k++ < PPA_SELECT_TMO)) barrier();
134 return r;
135 }
136
137 char ppa_wait( void )
138
139
140
141
142
143
144
145
146
147
148
149
150 { int k;
151 char r;
152
153 ppa_error_code = DID_OK;
154 k = 0;
155 while (!((r = in_p(1)) & 0x80)
156 && (k++ < PPA_SPIN_TMO) && !ppa_abort_flag )
157 if (need_resched && ppa_call_sched) schedule();
158 if (ppa_abort_flag) {
159 if (ppa_abort_flag == 1) ppa_error_code = DID_ABORT;
160 else { ppa_do_reset();
161 ppa_error_code = DID_RESET;
162 }
163 ppa_disconnect();
164 return 0;
165 }
166 if (k >= PPA_SPIN_TMO) {
167 ppa_error_code = DID_TIME_OUT;
168 ppa_disconnect();
169 return 0;
170 }
171 return (r & 0xf0);
172 }
173
174 int ppa_init( void )
175
176
177
178
179
180
181
182
183
184
185 { char r, s;
186
187 out_p(0,0xaa);
188 if (in_p(0) != (char) 0xaa) return 1;
189 ppa_disconnect();
190 ppa_connect();
191 out_p(2,0x6);
192 if ((in_p(1) & 0xf0) != 0xf0) return 2;
193 out_p(2,0x4);
194 if ((in_p(1) & 0xf0) != 0x80) return 3;
195 ppa_disconnect();
196 s = in_p(2);
197 out_p(2,0xec);
198 out_p(0,0x55);
199 r = in_p(0);
200 if (r != (char) 0xff) {
201 ppa_nybble = 1;
202 if (r != (char) 0x55) return 4;
203 out_p(0,0xaa); if (in_p(0) != (char) 0xaa) return 5;
204 }
205 out_p(2,s);
206 ppa_connect();
207 out_p(0,0x40); out_p(2,0x8); out_p(2,0xc);
208 ppa_disconnect();
209
210 return 0;
211 }
212
213 int ppa_start( Scsi_Cmnd * cmd )
214
215 { int k;
216
217 ppa_error_code = DID_OK;
218 ppa_abort_flag = 0;
219
220 if (cmd->target == PPA_INITIATOR) {
221 ppa_error_code = DID_BAD_TARGET;
222 return 0;
223 }
224 ppa_connect();
225 if (!ppa_select(PPA_INITIATOR,cmd->target)) {
226 ppa_disconnect();
227 ppa_error_code = DID_NO_CONNECT;
228 return 0;
229 }
230 out_p(2,0xc);
231
232 for (k=0; k < cmd->cmd_len; k++) {
233 if (!ppa_wait()) return 0;
234 out_p(0,cmd->cmnd[k]);
235 out_p(2,0xe);
236 out_p(2,0xc);
237 }
238
239 #ifdef PPA_DEBUG
240 printk("PPA: command out: ");
241 for (k=0; k < cmd->cmd_len; k++)
242 printk("%3x",(cmd->cmnd[k]) & 0xff );
243 printk("\n");
244 #endif
245
246 return 1;
247 }
248
249 int ppa_completion( Scsi_Cmnd * cmd )
250
251
252
253
254
255
256
257
258
259 { char r, l, h, v;
260 int dir, cnt, blen, fast, bulk;
261 char *buffer;
262
263 #ifdef PPA_DEBUG
264 int k;
265 #endif
266
267 if (!(r = ppa_wait())) return 0;
268 v = cmd->cmnd[0];
269 bulk = ((v==READ_6)||(v==READ_10)||(v==WRITE_6)||(v==WRITE_10));
270 buffer = cmd->request_buffer;
271 blen = cmd->request_bufflen;
272 cnt = 0; dir = 0;
273 if (r == (char) 0xc0) dir = 1;
274
275 ppa_port_delay = ppa_speed_high;
276
277 while (r != (char) 0xf0) {
278 if (((r & 0xc0) != 0xc0 ) || (cnt >= blen)) {
279 ppa_disconnect();
280 ppa_error_code = DID_ERROR;
281 return 0;
282 }
283 fast = bulk && ((blen - cnt) >= PPA_SECTOR_SIZE);
284 if (dir) do {
285 out_p(0,buffer[cnt++]);
286 out_p(2,0xe); out_p(2,0xc);
287 if (!fast) break;
288 } while (cnt % PPA_SECTOR_SIZE);
289 else {
290 if (ppa_nybble) do {
291 out_p(2,0x4); h = in_p(1);
292 out_p(2,0x6); l = in_p(1);
293 v = ((l >> 4) & 0x0f) + (h & 0xf0);
294 buffer[cnt++] = v;
295 if (!fast) break;
296 } while (cnt % PPA_SECTOR_SIZE);
297 else do {
298 out_p(2,0x25); v = in_p(0); out_p(2,0x27);
299 buffer[cnt++] = v;
300 if (!fast) break;
301 } while (cnt % PPA_SECTOR_SIZE);
302 if (!ppa_nybble) {
303 out_p(2,0x5); out_p(2,0x4);
304 }
305 out_p(2,0xc);
306 }
307 if (!(r = ppa_wait())) return 0;
308 }
309
310 ppa_port_delay = ppa_speed_low;
311
312 out_p(2,0x4);
313 h = in_p(1);
314 out_p(2,0x6);
315 l = in_p(1);
316 out_p(2,0xc);
317 r = ((l >> 4) & 0x0f) + (h & 0xf0);
318
319 out_p(2,0xe); out_p(2,0xc);
320 ppa_disconnect();
321
322 #ifdef PPA_DEBUG
323 printk("PPA: status: %x, data[%d]: ",r & STATUS_MASK,cnt);
324 if (cnt > 12) cnt = 12;
325 for (k=0; k < cnt; k++)
326 printk("%3x",buffer[k] & 0xff );
327 printk("\n");
328 #endif
329
330 return (r & STATUS_MASK);
331 }
332
333 int ppa_command( Scsi_Cmnd * cmd )
334
335 { int s;
336
337 s = 0;
338 if (ppa_start(cmd))
339 if (ppa_wait())
340 s = ppa_completion(cmd);
341 return s + (ppa_error_code << 16);
342 }
343
344 int ppa_queuecommand( Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
345
346
347
348
349
350
351 { int s;
352
353 ppa_current = cmd; ppa_done = done;
354 if (ppa_busy) return 0;
355 ppa_busy = 1;
356 while (ppa_current) {
357 cmd = ppa_current; done = ppa_done;
358 s = 0;
359 if (ppa_start(cmd))
360 if (ppa_wait())
361 s = ppa_completion(cmd);
362 cmd->result = s + (ppa_error_code << 16);
363 ppa_current = 0;
364 done(cmd);
365 }
366 ppa_busy = 0;
367 return 0;
368 }
369
370 int ppa_detect( Scsi_Host_Template * host )
371
372 { struct Scsi_Host *hreg;
373 int rs;
374
375
376
377 if (check_region(ppa_base,3)) {
378 printk("PPA: ports at 0x%3x are not available\n",ppa_base);
379 return 0;
380 }
381
382
383
384 ppa_port_delay = ppa_speed_low;
385
386 rs = ppa_init();
387 if (rs) {
388 printk("PPA: unable to initialise controller at 0x%x, error %d\n",
389 ppa_base,rs);
390 return 0;
391 }
392
393
394
395 host->proc_dir = &proc_scsi_ppa;
396
397 request_region(ppa_base,3,"ppa");
398
399 host->can_queue = PPA_CAN_QUEUE;
400
401 hreg = scsi_register(host,0);
402 hreg->io_port = ppa_base;
403 hreg->n_io_port = 3;
404 hreg->dma_channel = -1;
405
406 sprintf(ppa_info_string,
407 "PPA driver version %s using %d-bit mode on port 0x%x.",
408 PPA_VERSION,8-ppa_nybble*4,ppa_base);
409 host->name = ppa_info_string;
410
411 return 1;
412 }
413
414 int ppa_biosparam( Disk * disk, kdev_t dev, int ip[])
415
416
417
418
419
420
421
422 { ip[0] = 0x40;
423 ip[1] = 0x20;
424 ip[2] = (disk->capacity +1) / (ip[0] * ip[1]);
425 if (ip[2] > 1024) {
426 ip[0] = 0xff;
427 ip[1] = 0x3f;
428 ip[2] = (disk->capacity +1) / (ip[0] * ip[1]);
429 if (ip[2] > 1023)
430 ip[2] = 1023;
431 }
432 return 0;
433 }
434
435 int ppa_abort( Scsi_Cmnd * cmd )
436
437 { ppa_abort_flag = 1;
438 return SCSI_ABORT_SNOOZE;
439 }
440
441 int ppa_reset( Scsi_Cmnd * cmd )
442
443 { ppa_abort_flag = 2;
444 return SCSI_RESET_PUNT;
445 }
446
447 const char *ppa_info( struct Scsi_Host * host )
448
449 { return ppa_info_string;
450 }
451
452 #ifndef MODULE
453
454
455
456
457
458
459
460
461
462 void ppa_setup(char *str, int *ints)
463
464 { if (ints[0] > 0) ppa_base = ints[1];
465 if (ints[0] > 1) ppa_speed_high = ints[2];
466 if (ints[0] > 2) ppa_speed_low = ints[3];
467 if (ints[0] > 3) ppa_call_sched = ints[4];
468 if (ints[0] > 4) ppa_nybble = ints[5];
469 }
470
471 #else
472
473 Scsi_Host_Template driver_template = PPA;
474
475 #include "scsi_module.c"
476
477 #endif
478
479