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