]> Git Repo - linux.git/blob - drivers/ata/pata_parport/bpck6.c
arm64: avoid prototype warnings for syscalls
[linux.git] / drivers / ata / pata_parport / bpck6.c
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     ([email protected])
10                     Clive Turvey ([email protected])
11
12 */
13
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <linux/parport.h>
19 #include "pata_parport.h"
20
21 /* 60772 Commands */
22 #define ACCESS_REG              0x00
23 #define ACCESS_PORT             0x40
24
25 #define ACCESS_READ             0x00
26 #define ACCESS_WRITE            0x20
27
28 /* 60772 Command Prefix */
29 #define CMD_PREFIX_SET          0xe0    // Special command that modifies next command's operation
30 #define CMD_PREFIX_RESET        0xc0    // Resets current cmd modifier reg bits
31  #define PREFIX_IO16            0x01    // perform 16-bit wide I/O
32  #define PREFIX_FASTWR          0x04    // enable PPC mode fast-write
33  #define PREFIX_BLK             0x08    // enable block transfer mode
34
35 /* 60772 Registers */
36 #define REG_STATUS              0x00    // status register
37  #define STATUS_IRQA            0x01    // Peripheral IRQA line
38  #define STATUS_EEPROM_DO       0x40    // Serial EEPROM data bit
39 #define REG_VERSION             0x01    // PPC version register (read)
40 #define REG_HWCFG               0x02    // Hardware Config register
41 #define REG_RAMSIZE             0x03    // Size of RAM Buffer
42  #define RAMSIZE_128K           0x02
43 #define REG_EEPROM              0x06    // EEPROM control register
44  #define EEPROM_SK              0x01    // eeprom SK bit
45  #define EEPROM_DI              0x02    // eeprom DI bit
46  #define EEPROM_CS              0x04    // eeprom CS bit
47  #define EEPROM_EN              0x08    // eeprom output enable
48 #define REG_BLKSIZE             0x08    // Block transfer len (24 bit)
49
50 /* flags */
51 #define fifo_wait               0x10
52
53 /* DONT CHANGE THESE LEST YOU BREAK EVERYTHING - BIT FIELD DEPENDENCIES */
54 #define PPCMODE_UNI_SW          0
55 #define PPCMODE_UNI_FW          1
56 #define PPCMODE_BI_SW           2
57 #define PPCMODE_BI_FW           3
58 #define PPCMODE_EPP_BYTE        4
59 #define PPCMODE_EPP_WORD        5
60 #define PPCMODE_EPP_DWORD       6
61
62 static int mode_map[] = { PPCMODE_UNI_FW, PPCMODE_BI_FW, PPCMODE_EPP_BYTE,
63                           PPCMODE_EPP_WORD, PPCMODE_EPP_DWORD };
64
65 static void bpck6_send_cmd(struct pi_adapter *pi, u8 cmd)
66 {
67         switch (mode_map[pi->mode]) {
68         case PPCMODE_UNI_SW:
69         case PPCMODE_UNI_FW:
70         case PPCMODE_BI_SW:
71         case PPCMODE_BI_FW:
72                 parport_write_data(pi->pardev->port, cmd);
73                 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_AUTOFD);
74                 break;
75         case PPCMODE_EPP_BYTE:
76         case PPCMODE_EPP_WORD:
77         case PPCMODE_EPP_DWORD:
78                 pi->pardev->port->ops->epp_write_addr(pi->pardev->port, &cmd, 1, 0);
79                 break;
80         }
81 }
82
83 static u8 bpck6_rd_data_byte(struct pi_adapter *pi)
84 {
85         u8 data = 0;
86
87         switch (mode_map[pi->mode]) {
88         case PPCMODE_UNI_SW:
89         case PPCMODE_UNI_FW:
90                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
91                                                         PARPORT_CONTROL_INIT);
92                 data = parport_read_status(pi->pardev->port);
93                 data = ((data & 0x80) >> 1) | ((data & 0x38) >> 3);
94                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
95                                                         PARPORT_CONTROL_STROBE);
96                 data |= parport_read_status(pi->pardev->port) & 0xB8;
97                 break;
98         case PPCMODE_BI_SW:
99         case PPCMODE_BI_FW:
100                 parport_data_reverse(pi->pardev->port);
101                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
102                                 PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT);
103                 data = parport_read_data(pi->pardev->port);
104                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE, 0);
105                 parport_data_forward(pi->pardev->port);
106                 break;
107         case PPCMODE_EPP_BYTE:
108         case PPCMODE_EPP_WORD:
109         case PPCMODE_EPP_DWORD:
110                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, &data, 1, 0);
111                 break;
112         }
113
114         return data;
115 }
116
117 static void bpck6_wr_data_byte(struct pi_adapter *pi, u8 data)
118 {
119         switch (mode_map[pi->mode]) {
120         case PPCMODE_UNI_SW:
121         case PPCMODE_UNI_FW:
122         case PPCMODE_BI_SW:
123         case PPCMODE_BI_FW:
124                 parport_write_data(pi->pardev->port, data);
125                 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_INIT);
126                 break;
127         case PPCMODE_EPP_BYTE:
128         case PPCMODE_EPP_WORD:
129         case PPCMODE_EPP_DWORD:
130                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, &data, 1, 0);
131                 break;
132         }
133 }
134
135 static int bpck6_read_regr(struct pi_adapter *pi, int cont, int reg)
136 {
137         u8 port = cont ? reg | 8 : reg;
138
139         bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_READ);
140         return bpck6_rd_data_byte(pi);
141 }
142
143 static void bpck6_write_regr(struct pi_adapter *pi, int cont, int reg, int val)
144 {
145         u8 port = cont ? reg | 8 : reg;
146
147         bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_WRITE);
148         bpck6_wr_data_byte(pi, val);
149 }
150
151 static void bpck6_wait_for_fifo(struct pi_adapter *pi)
152 {
153         int i;
154
155         if (pi->private & fifo_wait) {
156                 for (i = 0; i < 20; i++)
157                         parport_read_status(pi->pardev->port);
158         }
159 }
160
161 static void bpck6_write_block(struct pi_adapter *pi, char *buf, int len)
162 {
163         u8 this, last;
164
165         bpck6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE);
166         bpck6_wr_data_byte(pi, (u8)len);
167         bpck6_wr_data_byte(pi, (u8)(len >> 8));
168         bpck6_wr_data_byte(pi, 0);
169
170         bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
171         bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_WRITE);
172
173         switch (mode_map[pi->mode]) {
174         case PPCMODE_UNI_SW:
175         case PPCMODE_BI_SW:
176                 while (len--) {
177                         parport_write_data(pi->pardev->port, *buf++);
178                         parport_frob_control(pi->pardev->port, 0,
179                                                         PARPORT_CONTROL_INIT);
180                 }
181                 break;
182         case PPCMODE_UNI_FW:
183         case PPCMODE_BI_FW:
184                 bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_FASTWR);
185
186                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
187                                                         PARPORT_CONTROL_STROBE);
188
189                 last = *buf;
190
191                 parport_write_data(pi->pardev->port, last);
192
193                 while (len) {
194                         this = *buf++;
195                         len--;
196
197                         if (this == last) {
198                                 parport_frob_control(pi->pardev->port, 0,
199                                                         PARPORT_CONTROL_INIT);
200                         } else {
201                                 parport_write_data(pi->pardev->port, this);
202                                 last = this;
203                         }
204                 }
205
206                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
207                                                         0);
208                 bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_FASTWR);
209                 break;
210         case PPCMODE_EPP_BYTE:
211                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
212                                                 len, PARPORT_EPP_FAST_8);
213                 bpck6_wait_for_fifo(pi);
214                 break;
215         case PPCMODE_EPP_WORD:
216                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
217                                                 len, PARPORT_EPP_FAST_16);
218                 bpck6_wait_for_fifo(pi);
219                 break;
220         case PPCMODE_EPP_DWORD:
221                 pi->pardev->port->ops->epp_write_data(pi->pardev->port, buf,
222                                                 len, PARPORT_EPP_FAST_32);
223                 bpck6_wait_for_fifo(pi);
224                 break;
225         }
226
227         bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
228 }
229
230 static void bpck6_read_block(struct pi_adapter *pi, char *buf, int len)
231 {
232         bpck6_send_cmd(pi, REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE);
233         bpck6_wr_data_byte(pi, (u8)len);
234         bpck6_wr_data_byte(pi, (u8)(len >> 8));
235         bpck6_wr_data_byte(pi, 0);
236
237         bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
238         bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_READ);
239
240         switch (mode_map[pi->mode]) {
241         case PPCMODE_UNI_SW:
242         case PPCMODE_UNI_FW:
243                 while (len) {
244                         u8 d;
245
246                         parport_frob_control(pi->pardev->port,
247                                         PARPORT_CONTROL_STROBE,
248                                         PARPORT_CONTROL_INIT); /* DATA STROBE */
249                         d = parport_read_status(pi->pardev->port);
250                         d = ((d & 0x80) >> 1) | ((d & 0x38) >> 3);
251                         parport_frob_control(pi->pardev->port,
252                                         PARPORT_CONTROL_STROBE,
253                                         PARPORT_CONTROL_STROBE);
254                         d |= parport_read_status(pi->pardev->port) & 0xB8;
255                         *buf++ = d;
256                         len--;
257                 }
258                 break;
259         case PPCMODE_BI_SW:
260         case PPCMODE_BI_FW:
261                 parport_data_reverse(pi->pardev->port);
262                 while (len) {
263                         parport_frob_control(pi->pardev->port,
264                                 PARPORT_CONTROL_STROBE,
265                                 PARPORT_CONTROL_STROBE | PARPORT_CONTROL_INIT);
266                         *buf++ = parport_read_data(pi->pardev->port);
267                         len--;
268                 }
269                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
270                                         0);
271                 parport_data_forward(pi->pardev->port);
272                 break;
273         case PPCMODE_EPP_BYTE:
274                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
275                                                 PARPORT_EPP_FAST_8);
276                 break;
277         case PPCMODE_EPP_WORD:
278                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
279                                                 PARPORT_EPP_FAST_16);
280                 break;
281         case PPCMODE_EPP_DWORD:
282                 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
283                                                 PARPORT_EPP_FAST_32);
284                 break;
285         }
286
287         bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
288 }
289
290 static int bpck6_open(struct pi_adapter *pi)
291 {
292         u8 i, j, k;
293
294         pi->saved_r0 = parport_read_data(pi->pardev->port);
295         pi->saved_r2 = parport_read_control(pi->pardev->port) & 0x5F;
296
297         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
298                                                 PARPORT_CONTROL_SELECT);
299         if (pi->saved_r0 == 'b')
300                 parport_write_data(pi->pardev->port, 'x');
301         parport_write_data(pi->pardev->port, 'b');
302         parport_write_data(pi->pardev->port, 'p');
303         parport_write_data(pi->pardev->port, pi->unit);
304         parport_write_data(pi->pardev->port, ~pi->unit);
305
306         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
307         parport_write_control(pi->pardev->port, PARPORT_CONTROL_INIT);
308
309         i = mode_map[pi->mode] & 0x0C;
310         if (i == 0)
311                 i = (mode_map[pi->mode] & 2) | 1;
312         parport_write_data(pi->pardev->port, i);
313
314         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
315                                                 PARPORT_CONTROL_SELECT);
316         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_AUTOFD,
317                                                 PARPORT_CONTROL_AUTOFD);
318
319         j = ((i & 0x08) << 4) | ((i & 0x07) << 3);
320         k = parport_read_status(pi->pardev->port) & 0xB8;
321         if (j != k)
322                 goto fail;
323
324         parport_frob_control(pi->pardev->port, PARPORT_CONTROL_AUTOFD, 0);
325         k = (parport_read_status(pi->pardev->port) & 0xB8) ^ 0xB8;
326         if (j != k)
327                 goto fail;
328
329         if (i & 4)      // EPP
330                 parport_frob_control(pi->pardev->port,
331                         PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
332         else                            // PPC/ECP
333                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
334
335         pi->private = 0;
336
337         bpck6_send_cmd(pi, ACCESS_REG | ACCESS_WRITE | REG_RAMSIZE);
338         bpck6_wr_data_byte(pi, RAMSIZE_128K);
339
340         bpck6_send_cmd(pi, ACCESS_REG | ACCESS_READ | REG_VERSION);
341         if ((bpck6_rd_data_byte(pi) & 0x3F) == 0x0C)
342                 pi->private |= fifo_wait;
343
344         return 1;
345
346 fail:
347         parport_write_control(pi->pardev->port, pi->saved_r2);
348         parport_write_data(pi->pardev->port, pi->saved_r0);
349
350         return 0; // FAIL
351 }
352
353 static void bpck6_deselect(struct pi_adapter *pi)
354 {
355         if (mode_map[pi->mode] & 4)     // EPP
356                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
357                                                         PARPORT_CONTROL_INIT);
358         else                                                            // PPC/ECP
359                 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
360                                                         PARPORT_CONTROL_SELECT);
361
362         parport_write_data(pi->pardev->port, pi->saved_r0);
363         parport_write_control(pi->pardev->port,
364                         pi->saved_r2 | PARPORT_CONTROL_SELECT);
365         parport_write_control(pi->pardev->port, pi->saved_r2);
366 }
367
368 static void bpck6_wr_extout(struct pi_adapter *pi, u8 regdata)
369 {
370         bpck6_send_cmd(pi, REG_VERSION | ACCESS_REG | ACCESS_WRITE);
371         bpck6_wr_data_byte(pi, (u8)((regdata & 0x03) << 6));
372 }
373
374 static void bpck6_connect(struct pi_adapter *pi)
375 {
376         dev_dbg(&pi->dev, "connect\n");
377
378         bpck6_open(pi);
379         bpck6_wr_extout(pi, 0x3);
380 }
381
382 static void bpck6_disconnect(struct pi_adapter *pi)
383 {
384         dev_dbg(&pi->dev, "disconnect\n");
385         bpck6_wr_extout(pi, 0x0);
386         bpck6_deselect(pi);
387 }
388
389 static int bpck6_test_port(struct pi_adapter *pi)   /* check for 8-bit port */
390 {
391         dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
392                 pi->pardev->port->modes, pi->pardev->port->base);
393
394         /* look at the parport device to see what modes we can use */
395         if (pi->pardev->port->modes & PARPORT_MODE_EPP)
396                 return 5; /* Can do EPP */
397         if (pi->pardev->port->modes & PARPORT_MODE_TRISTATE)
398                 return 2;
399         return 1; /* Just flat SPP */
400 }
401
402 static int bpck6_probe_unit(struct pi_adapter *pi)
403 {
404         int out, saved_mode;
405
406         dev_dbg(&pi->dev, "PROBE UNIT %x on port:%x\n", pi->unit, pi->port);
407
408         saved_mode = pi->mode;
409         /*LOWER DOWN TO UNIDIRECTIONAL*/
410         pi->mode = 0;
411
412         out = bpck6_open(pi);
413
414         dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
415
416         if(out)
417         {
418                 bpck6_deselect(pi);
419                 dev_dbg(&pi->dev, "leaving probe\n");
420                 pi->mode = saved_mode;
421                return(1);
422         }
423         else
424         {
425                 dev_dbg(&pi->dev, "Failed open\n");
426                 pi->mode = saved_mode;
427                 return(0);
428         }
429 }
430
431 static void bpck6_log_adapter(struct pi_adapter *pi)
432 {
433         char *mode_string[5]=
434                 {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
435
436         dev_info(&pi->dev, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
437                 pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
438 }
439
440 static struct pi_protocol bpck6 = {
441         .owner          = THIS_MODULE,
442         .name           = "bpck6",
443         .max_mode       = 5,
444         .epp_first      = 2, /* 2-5 use epp (need 8 ports) */
445         .max_units      = 255,
446         .write_regr     = bpck6_write_regr,
447         .read_regr      = bpck6_read_regr,
448         .write_block    = bpck6_write_block,
449         .read_block     = bpck6_read_block,
450         .connect        = bpck6_connect,
451         .disconnect     = bpck6_disconnect,
452         .test_port      = bpck6_test_port,
453         .probe_unit     = bpck6_probe_unit,
454         .log_adapter    = bpck6_log_adapter,
455 };
456
457 MODULE_LICENSE("GPL");
458 MODULE_AUTHOR("Micro Solutions Inc.");
459 MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
460 module_pata_parport_driver(bpck6);
This page took 0.059691 seconds and 4 git commands to generate.