diff options
Diffstat (limited to 'drivers/block/paride/ppc6lnx.c')
-rw-r--r-- | drivers/block/paride/ppc6lnx.c | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/drivers/block/paride/ppc6lnx.c b/drivers/block/paride/ppc6lnx.c new file mode 100644 index 000000000000..5e5521d3b1dd --- /dev/null +++ b/drivers/block/paride/ppc6lnx.c | |||
@@ -0,0 +1,726 @@ | |||
1 | /* | ||
2 | ppc6lnx.c (c) 2001 Micro Solutions Inc. | ||
3 | Released under the terms of the GNU General Public license | ||
4 | |||
5 | ppc6lnx.c is a par of the protocol driver for the Micro Solutions | ||
6 | "BACKPACK" parallel port IDE adapter | ||
7 | (Works on Series 6 drives) | ||
8 | |||
9 | */ | ||
10 | |||
11 | //*************************************************************************** | ||
12 | |||
13 | // PPC 6 Code in C sanitized for LINUX | ||
14 | // Original x86 ASM by Ron, Converted to C by Clive | ||
15 | |||
16 | //*************************************************************************** | ||
17 | |||
18 | |||
19 | #define port_stb 1 | ||
20 | #define port_afd 2 | ||
21 | #define cmd_stb port_afd | ||
22 | #define port_init 4 | ||
23 | #define data_stb port_init | ||
24 | #define port_sel 8 | ||
25 | #define port_int 16 | ||
26 | #define port_dir 0x20 | ||
27 | |||
28 | #define ECR_EPP 0x80 | ||
29 | #define ECR_BI 0x20 | ||
30 | |||
31 | //*************************************************************************** | ||
32 | |||
33 | // 60772 Commands | ||
34 | |||
35 | #define ACCESS_REG 0x00 | ||
36 | #define ACCESS_PORT 0x40 | ||
37 | |||
38 | #define ACCESS_READ 0x00 | ||
39 | #define ACCESS_WRITE 0x20 | ||
40 | |||
41 | // 60772 Command Prefix | ||
42 | |||
43 | #define CMD_PREFIX_SET 0xe0 // Special command that modifies the next command's operation | ||
44 | #define CMD_PREFIX_RESET 0xc0 // Resets current cmd modifier reg bits | ||
45 | #define PREFIX_IO16 0x01 // perform 16-bit wide I/O | ||
46 | #define PREFIX_FASTWR 0x04 // enable PPC mode fast-write | ||
47 | #define PREFIX_BLK 0x08 // enable block transfer mode | ||
48 | |||
49 | // 60772 Registers | ||
50 | |||
51 | #define REG_STATUS 0x00 // status register | ||
52 | #define STATUS_IRQA 0x01 // Peripheral IRQA line | ||
53 | #define STATUS_EEPROM_DO 0x40 // Serial EEPROM data bit | ||
54 | #define REG_VERSION 0x01 // PPC version register (read) | ||
55 | #define REG_HWCFG 0x02 // Hardware Config register | ||
56 | #define REG_RAMSIZE 0x03 // Size of RAM Buffer | ||
57 | #define RAMSIZE_128K 0x02 | ||
58 | #define REG_EEPROM 0x06 // EEPROM control register | ||
59 | #define EEPROM_SK 0x01 // eeprom SK bit | ||
60 | #define EEPROM_DI 0x02 // eeprom DI bit | ||
61 | #define EEPROM_CS 0x04 // eeprom CS bit | ||
62 | #define EEPROM_EN 0x08 // eeprom output enable | ||
63 | #define REG_BLKSIZE 0x08 // Block transfer len (24 bit) | ||
64 | |||
65 | //*************************************************************************** | ||
66 | |||
67 | typedef struct ppc_storage { | ||
68 | u16 lpt_addr; // LPT base address | ||
69 | u8 ppc_id; | ||
70 | u8 mode; // operating mode | ||
71 | // 0 = PPC Uni SW | ||
72 | // 1 = PPC Uni FW | ||
73 | // 2 = PPC Bi SW | ||
74 | // 3 = PPC Bi FW | ||
75 | // 4 = EPP Byte | ||
76 | // 5 = EPP Word | ||
77 | // 6 = EPP Dword | ||
78 | u8 ppc_flags; | ||
79 | u8 org_data; // original LPT data port contents | ||
80 | u8 org_ctrl; // original LPT control port contents | ||
81 | u8 cur_ctrl; // current control port contents | ||
82 | } Interface; | ||
83 | |||
84 | //*************************************************************************** | ||
85 | |||
86 | // ppc_flags | ||
87 | |||
88 | #define fifo_wait 0x10 | ||
89 | |||
90 | //*************************************************************************** | ||
91 | |||
92 | // DONT CHANGE THESE LEST YOU BREAK EVERYTHING - BIT FIELD DEPENDENCIES | ||
93 | |||
94 | #define PPCMODE_UNI_SW 0 | ||
95 | #define PPCMODE_UNI_FW 1 | ||
96 | #define PPCMODE_BI_SW 2 | ||
97 | #define PPCMODE_BI_FW 3 | ||
98 | #define PPCMODE_EPP_BYTE 4 | ||
99 | #define PPCMODE_EPP_WORD 5 | ||
100 | #define PPCMODE_EPP_DWORD 6 | ||
101 | |||
102 | //*************************************************************************** | ||
103 | |||
104 | static int ppc6_select(Interface *ppc); | ||
105 | static void ppc6_deselect(Interface *ppc); | ||
106 | static void ppc6_send_cmd(Interface *ppc, u8 cmd); | ||
107 | static void ppc6_wr_data_byte(Interface *ppc, u8 data); | ||
108 | static u8 ppc6_rd_data_byte(Interface *ppc); | ||
109 | static u8 ppc6_rd_port(Interface *ppc, u8 port); | ||
110 | static void ppc6_wr_port(Interface *ppc, u8 port, u8 data); | ||
111 | static void ppc6_rd_data_blk(Interface *ppc, u8 *data, long count); | ||
112 | static void ppc6_wait_for_fifo(Interface *ppc); | ||
113 | static void ppc6_wr_data_blk(Interface *ppc, u8 *data, long count); | ||
114 | static void ppc6_rd_port16_blk(Interface *ppc, u8 port, u8 *data, long length); | ||
115 | static void ppc6_wr_port16_blk(Interface *ppc, u8 port, u8 *data, long length); | ||
116 | static void ppc6_wr_extout(Interface *ppc, u8 regdata); | ||
117 | static int ppc6_open(Interface *ppc); | ||
118 | static void ppc6_close(Interface *ppc); | ||
119 | |||
120 | //*************************************************************************** | ||
121 | |||
122 | static int ppc6_select(Interface *ppc) | ||
123 | { | ||
124 | u8 i, j, k; | ||
125 | |||
126 | i = inb(ppc->lpt_addr + 1); | ||
127 | |||
128 | if (i & 1) | ||
129 | outb(i, ppc->lpt_addr + 1); | ||
130 | |||
131 | ppc->org_data = inb(ppc->lpt_addr); | ||
132 | |||
133 | ppc->org_ctrl = inb(ppc->lpt_addr + 2) & 0x5F; // readback ctrl | ||
134 | |||
135 | ppc->cur_ctrl = ppc->org_ctrl; | ||
136 | |||
137 | ppc->cur_ctrl |= port_sel; | ||
138 | |||
139 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
140 | |||
141 | if (ppc->org_data == 'b') | ||
142 | outb('x', ppc->lpt_addr); | ||
143 | |||
144 | outb('b', ppc->lpt_addr); | ||
145 | outb('p', ppc->lpt_addr); | ||
146 | outb(ppc->ppc_id, ppc->lpt_addr); | ||
147 | outb(~ppc->ppc_id,ppc->lpt_addr); | ||
148 | |||
149 | ppc->cur_ctrl &= ~port_sel; | ||
150 | |||
151 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
152 | |||
153 | ppc->cur_ctrl = (ppc->cur_ctrl & port_int) | port_init; | ||
154 | |||
155 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
156 | |||
157 | i = ppc->mode & 0x0C; | ||
158 | |||
159 | if (i == 0) | ||
160 | i = (ppc->mode & 2) | 1; | ||
161 | |||
162 | outb(i, ppc->lpt_addr); | ||
163 | |||
164 | ppc->cur_ctrl |= port_sel; | ||
165 | |||
166 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
167 | |||
168 | // DELAY | ||
169 | |||
170 | ppc->cur_ctrl |= port_afd; | ||
171 | |||
172 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
173 | |||
174 | j = ((i & 0x08) << 4) | ((i & 0x07) << 3); | ||
175 | |||
176 | k = inb(ppc->lpt_addr + 1) & 0xB8; | ||
177 | |||
178 | if (j == k) | ||
179 | { | ||
180 | ppc->cur_ctrl &= ~port_afd; | ||
181 | |||
182 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
183 | |||
184 | k = (inb(ppc->lpt_addr + 1) & 0xB8) ^ 0xB8; | ||
185 | |||
186 | if (j == k) | ||
187 | { | ||
188 | if (i & 4) // EPP | ||
189 | ppc->cur_ctrl &= ~(port_sel | port_init); | ||
190 | else // PPC/ECP | ||
191 | ppc->cur_ctrl &= ~port_sel; | ||
192 | |||
193 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
194 | |||
195 | return(1); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | outb(ppc->org_ctrl, ppc->lpt_addr + 2); | ||
200 | |||
201 | outb(ppc->org_data, ppc->lpt_addr); | ||
202 | |||
203 | return(0); // FAIL | ||
204 | } | ||
205 | |||
206 | //*************************************************************************** | ||
207 | |||
208 | static void ppc6_deselect(Interface *ppc) | ||
209 | { | ||
210 | if (ppc->mode & 4) // EPP | ||
211 | ppc->cur_ctrl |= port_init; | ||
212 | else // PPC/ECP | ||
213 | ppc->cur_ctrl |= port_sel; | ||
214 | |||
215 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
216 | |||
217 | outb(ppc->org_data, ppc->lpt_addr); | ||
218 | |||
219 | outb((ppc->org_ctrl | port_sel), ppc->lpt_addr + 2); | ||
220 | |||
221 | outb(ppc->org_ctrl, ppc->lpt_addr + 2); | ||
222 | } | ||
223 | |||
224 | //*************************************************************************** | ||
225 | |||
226 | static void ppc6_send_cmd(Interface *ppc, u8 cmd) | ||
227 | { | ||
228 | switch(ppc->mode) | ||
229 | { | ||
230 | case PPCMODE_UNI_SW : | ||
231 | case PPCMODE_UNI_FW : | ||
232 | case PPCMODE_BI_SW : | ||
233 | case PPCMODE_BI_FW : | ||
234 | { | ||
235 | outb(cmd, ppc->lpt_addr); | ||
236 | |||
237 | ppc->cur_ctrl ^= cmd_stb; | ||
238 | |||
239 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
240 | |||
241 | break; | ||
242 | } | ||
243 | |||
244 | case PPCMODE_EPP_BYTE : | ||
245 | case PPCMODE_EPP_WORD : | ||
246 | case PPCMODE_EPP_DWORD : | ||
247 | { | ||
248 | outb(cmd, ppc->lpt_addr + 3); | ||
249 | |||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | //*************************************************************************** | ||
256 | |||
257 | static void ppc6_wr_data_byte(Interface *ppc, u8 data) | ||
258 | { | ||
259 | switch(ppc->mode) | ||
260 | { | ||
261 | case PPCMODE_UNI_SW : | ||
262 | case PPCMODE_UNI_FW : | ||
263 | case PPCMODE_BI_SW : | ||
264 | case PPCMODE_BI_FW : | ||
265 | { | ||
266 | outb(data, ppc->lpt_addr); | ||
267 | |||
268 | ppc->cur_ctrl ^= data_stb; | ||
269 | |||
270 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
271 | |||
272 | break; | ||
273 | } | ||
274 | |||
275 | case PPCMODE_EPP_BYTE : | ||
276 | case PPCMODE_EPP_WORD : | ||
277 | case PPCMODE_EPP_DWORD : | ||
278 | { | ||
279 | outb(data, ppc->lpt_addr + 4); | ||
280 | |||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | //*************************************************************************** | ||
287 | |||
288 | static u8 ppc6_rd_data_byte(Interface *ppc) | ||
289 | { | ||
290 | u8 data = 0; | ||
291 | |||
292 | switch(ppc->mode) | ||
293 | { | ||
294 | case PPCMODE_UNI_SW : | ||
295 | case PPCMODE_UNI_FW : | ||
296 | { | ||
297 | ppc->cur_ctrl = (ppc->cur_ctrl & ~port_stb) ^ data_stb; | ||
298 | |||
299 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
300 | |||
301 | // DELAY | ||
302 | |||
303 | data = inb(ppc->lpt_addr + 1); | ||
304 | |||
305 | data = ((data & 0x80) >> 1) | ((data & 0x38) >> 3); | ||
306 | |||
307 | ppc->cur_ctrl |= port_stb; | ||
308 | |||
309 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
310 | |||
311 | // DELAY | ||
312 | |||
313 | data |= inb(ppc->lpt_addr + 1) & 0xB8; | ||
314 | |||
315 | break; | ||
316 | } | ||
317 | |||
318 | case PPCMODE_BI_SW : | ||
319 | case PPCMODE_BI_FW : | ||
320 | { | ||
321 | ppc->cur_ctrl |= port_dir; | ||
322 | |||
323 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
324 | |||
325 | ppc->cur_ctrl = (ppc->cur_ctrl | port_stb) ^ data_stb; | ||
326 | |||
327 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
328 | |||
329 | data = inb(ppc->lpt_addr); | ||
330 | |||
331 | ppc->cur_ctrl &= ~port_stb; | ||
332 | |||
333 | outb(ppc->cur_ctrl,ppc->lpt_addr + 2); | ||
334 | |||
335 | ppc->cur_ctrl &= ~port_dir; | ||
336 | |||
337 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
338 | |||
339 | break; | ||
340 | } | ||
341 | |||
342 | case PPCMODE_EPP_BYTE : | ||
343 | case PPCMODE_EPP_WORD : | ||
344 | case PPCMODE_EPP_DWORD : | ||
345 | { | ||
346 | outb((ppc->cur_ctrl | port_dir),ppc->lpt_addr + 2); | ||
347 | |||
348 | data = inb(ppc->lpt_addr + 4); | ||
349 | |||
350 | outb(ppc->cur_ctrl,ppc->lpt_addr + 2); | ||
351 | |||
352 | break; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | return(data); | ||
357 | } | ||
358 | |||
359 | //*************************************************************************** | ||
360 | |||
361 | static u8 ppc6_rd_port(Interface *ppc, u8 port) | ||
362 | { | ||
363 | ppc6_send_cmd(ppc,(u8)(port | ACCESS_PORT | ACCESS_READ)); | ||
364 | |||
365 | return(ppc6_rd_data_byte(ppc)); | ||
366 | } | ||
367 | |||
368 | //*************************************************************************** | ||
369 | |||
370 | static void ppc6_wr_port(Interface *ppc, u8 port, u8 data) | ||
371 | { | ||
372 | ppc6_send_cmd(ppc,(u8)(port | ACCESS_PORT | ACCESS_WRITE)); | ||
373 | |||
374 | ppc6_wr_data_byte(ppc, data); | ||
375 | } | ||
376 | |||
377 | //*************************************************************************** | ||
378 | |||
379 | static void ppc6_rd_data_blk(Interface *ppc, u8 *data, long count) | ||
380 | { | ||
381 | switch(ppc->mode) | ||
382 | { | ||
383 | case PPCMODE_UNI_SW : | ||
384 | case PPCMODE_UNI_FW : | ||
385 | { | ||
386 | while(count) | ||
387 | { | ||
388 | u8 d; | ||
389 | |||
390 | ppc->cur_ctrl = (ppc->cur_ctrl & ~port_stb) ^ data_stb; | ||
391 | |||
392 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
393 | |||
394 | // DELAY | ||
395 | |||
396 | d = inb(ppc->lpt_addr + 1); | ||
397 | |||
398 | d = ((d & 0x80) >> 1) | ((d & 0x38) >> 3); | ||
399 | |||
400 | ppc->cur_ctrl |= port_stb; | ||
401 | |||
402 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
403 | |||
404 | // DELAY | ||
405 | |||
406 | d |= inb(ppc->lpt_addr + 1) & 0xB8; | ||
407 | |||
408 | *data++ = d; | ||
409 | count--; | ||
410 | } | ||
411 | |||
412 | break; | ||
413 | } | ||
414 | |||
415 | case PPCMODE_BI_SW : | ||
416 | case PPCMODE_BI_FW : | ||
417 | { | ||
418 | ppc->cur_ctrl |= port_dir; | ||
419 | |||
420 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
421 | |||
422 | ppc->cur_ctrl |= port_stb; | ||
423 | |||
424 | while(count) | ||
425 | { | ||
426 | ppc->cur_ctrl ^= data_stb; | ||
427 | |||
428 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
429 | |||
430 | *data++ = inb(ppc->lpt_addr); | ||
431 | count--; | ||
432 | } | ||
433 | |||
434 | ppc->cur_ctrl &= ~port_stb; | ||
435 | |||
436 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
437 | |||
438 | ppc->cur_ctrl &= ~port_dir; | ||
439 | |||
440 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
441 | |||
442 | break; | ||
443 | } | ||
444 | |||
445 | case PPCMODE_EPP_BYTE : | ||
446 | { | ||
447 | outb((ppc->cur_ctrl | port_dir), ppc->lpt_addr + 2); | ||
448 | |||
449 | // DELAY | ||
450 | |||
451 | while(count) | ||
452 | { | ||
453 | *data++ = inb(ppc->lpt_addr + 4); | ||
454 | count--; | ||
455 | } | ||
456 | |||
457 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
458 | |||
459 | break; | ||
460 | } | ||
461 | |||
462 | case PPCMODE_EPP_WORD : | ||
463 | { | ||
464 | outb((ppc->cur_ctrl | port_dir), ppc->lpt_addr + 2); | ||
465 | |||
466 | // DELAY | ||
467 | |||
468 | while(count > 1) | ||
469 | { | ||
470 | *((u16 *)data) = inw(ppc->lpt_addr + 4); | ||
471 | data += 2; | ||
472 | count -= 2; | ||
473 | } | ||
474 | |||
475 | while(count) | ||
476 | { | ||
477 | *data++ = inb(ppc->lpt_addr + 4); | ||
478 | count--; | ||
479 | } | ||
480 | |||
481 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
482 | |||
483 | break; | ||
484 | } | ||
485 | |||
486 | case PPCMODE_EPP_DWORD : | ||
487 | { | ||
488 | outb((ppc->cur_ctrl | port_dir),ppc->lpt_addr + 2); | ||
489 | |||
490 | // DELAY | ||
491 | |||
492 | while(count > 3) | ||
493 | { | ||
494 | *((u32 *)data) = inl(ppc->lpt_addr + 4); | ||
495 | data += 4; | ||
496 | count -= 4; | ||
497 | } | ||
498 | |||
499 | while(count) | ||
500 | { | ||
501 | *data++ = inb(ppc->lpt_addr + 4); | ||
502 | count--; | ||
503 | } | ||
504 | |||
505 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
506 | |||
507 | break; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | } | ||
512 | |||
513 | //*************************************************************************** | ||
514 | |||
515 | static void ppc6_wait_for_fifo(Interface *ppc) | ||
516 | { | ||
517 | int i; | ||
518 | |||
519 | if (ppc->ppc_flags & fifo_wait) | ||
520 | { | ||
521 | for(i=0; i<20; i++) | ||
522 | inb(ppc->lpt_addr + 1); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | //*************************************************************************** | ||
527 | |||
528 | static void ppc6_wr_data_blk(Interface *ppc, u8 *data, long count) | ||
529 | { | ||
530 | switch(ppc->mode) | ||
531 | { | ||
532 | case PPCMODE_UNI_SW : | ||
533 | case PPCMODE_BI_SW : | ||
534 | { | ||
535 | while(count--) | ||
536 | { | ||
537 | outb(*data++, ppc->lpt_addr); | ||
538 | |||
539 | ppc->cur_ctrl ^= data_stb; | ||
540 | |||
541 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
542 | } | ||
543 | |||
544 | break; | ||
545 | } | ||
546 | |||
547 | case PPCMODE_UNI_FW : | ||
548 | case PPCMODE_BI_FW : | ||
549 | { | ||
550 | u8 this, last; | ||
551 | |||
552 | ppc6_send_cmd(ppc,(CMD_PREFIX_SET | PREFIX_FASTWR)); | ||
553 | |||
554 | ppc->cur_ctrl |= port_stb; | ||
555 | |||
556 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
557 | |||
558 | last = *data; | ||
559 | |||
560 | outb(last, ppc->lpt_addr); | ||
561 | |||
562 | while(count) | ||
563 | { | ||
564 | this = *data++; | ||
565 | count--; | ||
566 | |||
567 | if (this == last) | ||
568 | { | ||
569 | ppc->cur_ctrl ^= data_stb; | ||
570 | |||
571 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
572 | } | ||
573 | else | ||
574 | { | ||
575 | outb(this, ppc->lpt_addr); | ||
576 | |||
577 | last = this; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | ppc->cur_ctrl &= ~port_stb; | ||
582 | |||
583 | outb(ppc->cur_ctrl, ppc->lpt_addr + 2); | ||
584 | |||
585 | ppc6_send_cmd(ppc,(CMD_PREFIX_RESET | PREFIX_FASTWR)); | ||
586 | |||
587 | break; | ||
588 | } | ||
589 | |||
590 | case PPCMODE_EPP_BYTE : | ||
591 | { | ||
592 | while(count) | ||
593 | { | ||
594 | outb(*data++,ppc->lpt_addr + 4); | ||
595 | count--; | ||
596 | } | ||
597 | |||
598 | ppc6_wait_for_fifo(ppc); | ||
599 | |||
600 | break; | ||
601 | } | ||
602 | |||
603 | case PPCMODE_EPP_WORD : | ||
604 | { | ||
605 | while(count > 1) | ||
606 | { | ||
607 | outw(*((u16 *)data),ppc->lpt_addr + 4); | ||
608 | data += 2; | ||
609 | count -= 2; | ||
610 | } | ||
611 | |||
612 | while(count) | ||
613 | { | ||
614 | outb(*data++,ppc->lpt_addr + 4); | ||
615 | count--; | ||
616 | } | ||
617 | |||
618 | ppc6_wait_for_fifo(ppc); | ||
619 | |||
620 | break; | ||
621 | } | ||
622 | |||
623 | case PPCMODE_EPP_DWORD : | ||
624 | { | ||
625 | while(count > 3) | ||
626 | { | ||
627 | outl(*((u32 *)data),ppc->lpt_addr + 4); | ||
628 | data += 4; | ||
629 | count -= 4; | ||
630 | } | ||
631 | |||
632 | while(count) | ||
633 | { | ||
634 | outb(*data++,ppc->lpt_addr + 4); | ||
635 | count--; | ||
636 | } | ||
637 | |||
638 | ppc6_wait_for_fifo(ppc); | ||
639 | |||
640 | break; | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | |||
645 | //*************************************************************************** | ||
646 | |||
647 | static void ppc6_rd_port16_blk(Interface *ppc, u8 port, u8 *data, long length) | ||
648 | { | ||
649 | length = length << 1; | ||
650 | |||
651 | ppc6_send_cmd(ppc, (REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE)); | ||
652 | ppc6_wr_data_byte(ppc,(u8)length); | ||
653 | ppc6_wr_data_byte(ppc,(u8)(length >> 8)); | ||
654 | ppc6_wr_data_byte(ppc,0); | ||
655 | |||
656 | ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK)); | ||
657 | |||
658 | ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_READ)); | ||
659 | |||
660 | ppc6_rd_data_blk(ppc, data, length); | ||
661 | |||
662 | ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK)); | ||
663 | } | ||
664 | |||
665 | //*************************************************************************** | ||
666 | |||
667 | static void ppc6_wr_port16_blk(Interface *ppc, u8 port, u8 *data, long length) | ||
668 | { | ||
669 | length = length << 1; | ||
670 | |||
671 | ppc6_send_cmd(ppc, (REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE)); | ||
672 | ppc6_wr_data_byte(ppc,(u8)length); | ||
673 | ppc6_wr_data_byte(ppc,(u8)(length >> 8)); | ||
674 | ppc6_wr_data_byte(ppc,0); | ||
675 | |||
676 | ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK)); | ||
677 | |||
678 | ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_WRITE)); | ||
679 | |||
680 | ppc6_wr_data_blk(ppc, data, length); | ||
681 | |||
682 | ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK)); | ||
683 | } | ||
684 | |||
685 | //*************************************************************************** | ||
686 | |||
687 | static void ppc6_wr_extout(Interface *ppc, u8 regdata) | ||
688 | { | ||
689 | ppc6_send_cmd(ppc,(REG_VERSION | ACCESS_REG | ACCESS_WRITE)); | ||
690 | |||
691 | ppc6_wr_data_byte(ppc, (u8)((regdata & 0x03) << 6)); | ||
692 | } | ||
693 | |||
694 | //*************************************************************************** | ||
695 | |||
696 | static int ppc6_open(Interface *ppc) | ||
697 | { | ||
698 | int ret; | ||
699 | |||
700 | ret = ppc6_select(ppc); | ||
701 | |||
702 | if (ret == 0) | ||
703 | return(ret); | ||
704 | |||
705 | ppc->ppc_flags &= ~fifo_wait; | ||
706 | |||
707 | ppc6_send_cmd(ppc, (ACCESS_REG | ACCESS_WRITE | REG_RAMSIZE)); | ||
708 | ppc6_wr_data_byte(ppc, RAMSIZE_128K); | ||
709 | |||
710 | ppc6_send_cmd(ppc, (ACCESS_REG | ACCESS_READ | REG_VERSION)); | ||
711 | |||
712 | if ((ppc6_rd_data_byte(ppc) & 0x3F) == 0x0C) | ||
713 | ppc->ppc_flags |= fifo_wait; | ||
714 | |||
715 | return(ret); | ||
716 | } | ||
717 | |||
718 | //*************************************************************************** | ||
719 | |||
720 | static void ppc6_close(Interface *ppc) | ||
721 | { | ||
722 | ppc6_deselect(ppc); | ||
723 | } | ||
724 | |||
725 | //*************************************************************************** | ||
726 | |||