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