2 backpack.c (c) 2001 Micro Solutions Inc.
3 Released under the terms of the GNU General Public license
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)
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"
22 #define ACCESS_REG 0x00
23 #define ACCESS_PORT 0x40
25 #define ACCESS_READ 0x00
26 #define ACCESS_WRITE 0x20
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
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)
51 #define fifo_wait 0x10
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
62 static int mode_map[] = { PPCMODE_UNI_FW, PPCMODE_BI_FW, PPCMODE_EPP_BYTE,
63 PPCMODE_EPP_WORD, PPCMODE_EPP_DWORD };
65 static void bpck6_send_cmd(struct pi_adapter *pi, u8 cmd)
67 switch (mode_map[pi->mode]) {
72 parport_write_data(pi->pardev->port, cmd);
73 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_AUTOFD);
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);
83 static u8 bpck6_rd_data_byte(struct pi_adapter *pi)
87 switch (mode_map[pi->mode]) {
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;
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);
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);
117 static void bpck6_wr_data_byte(struct pi_adapter *pi, u8 data)
119 switch (mode_map[pi->mode]) {
124 parport_write_data(pi->pardev->port, data);
125 parport_frob_control(pi->pardev->port, 0, PARPORT_CONTROL_INIT);
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);
135 static int bpck6_read_regr(struct pi_adapter *pi, int cont, int reg)
137 u8 port = cont ? reg | 8 : reg;
139 bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_READ);
140 return bpck6_rd_data_byte(pi);
143 static void bpck6_write_regr(struct pi_adapter *pi, int cont, int reg, int val)
145 u8 port = cont ? reg | 8 : reg;
147 bpck6_send_cmd(pi, port | ACCESS_PORT | ACCESS_WRITE);
148 bpck6_wr_data_byte(pi, val);
151 static void bpck6_wait_for_fifo(struct pi_adapter *pi)
155 if (pi->private & fifo_wait) {
156 for (i = 0; i < 20; i++)
157 parport_read_status(pi->pardev->port);
161 static void bpck6_write_block(struct pi_adapter *pi, char *buf, int len)
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);
170 bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
171 bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_WRITE);
173 switch (mode_map[pi->mode]) {
177 parport_write_data(pi->pardev->port, *buf++);
178 parport_frob_control(pi->pardev->port, 0,
179 PARPORT_CONTROL_INIT);
184 bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_FASTWR);
186 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
187 PARPORT_CONTROL_STROBE);
191 parport_write_data(pi->pardev->port, last);
198 parport_frob_control(pi->pardev->port, 0,
199 PARPORT_CONTROL_INIT);
201 parport_write_data(pi->pardev->port, this);
206 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
208 bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_FASTWR);
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);
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);
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);
227 bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
230 static void bpck6_read_block(struct pi_adapter *pi, char *buf, int len)
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);
237 bpck6_send_cmd(pi, CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK);
238 bpck6_send_cmd(pi, ATA_REG_DATA | ACCESS_PORT | ACCESS_READ);
240 switch (mode_map[pi->mode]) {
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;
261 parport_data_reverse(pi->pardev->port);
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);
269 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_STROBE,
271 parport_data_forward(pi->pardev->port);
273 case PPCMODE_EPP_BYTE:
274 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
277 case PPCMODE_EPP_WORD:
278 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
279 PARPORT_EPP_FAST_16);
281 case PPCMODE_EPP_DWORD:
282 pi->pardev->port->ops->epp_read_data(pi->pardev->port, buf, len,
283 PARPORT_EPP_FAST_32);
287 bpck6_send_cmd(pi, CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK);
290 static int bpck6_open(struct pi_adapter *pi)
294 pi->saved_r0 = parport_read_data(pi->pardev->port);
295 pi->saved_r2 = parport_read_control(pi->pardev->port) & 0x5F;
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);
306 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
307 parport_write_control(pi->pardev->port, PARPORT_CONTROL_INIT);
309 i = mode_map[pi->mode] & 0x0C;
311 i = (mode_map[pi->mode] & 2) | 1;
312 parport_write_data(pi->pardev->port, i);
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);
319 j = ((i & 0x08) << 4) | ((i & 0x07) << 3);
320 k = parport_read_status(pi->pardev->port) & 0xB8;
324 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_AUTOFD, 0);
325 k = (parport_read_status(pi->pardev->port) & 0xB8) ^ 0xB8;
330 parport_frob_control(pi->pardev->port,
331 PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
333 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
337 bpck6_send_cmd(pi, ACCESS_REG | ACCESS_WRITE | REG_RAMSIZE);
338 bpck6_wr_data_byte(pi, RAMSIZE_128K);
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;
347 parport_write_control(pi->pardev->port, pi->saved_r2);
348 parport_write_data(pi->pardev->port, pi->saved_r0);
353 static void bpck6_deselect(struct pi_adapter *pi)
355 if (mode_map[pi->mode] & 4) // EPP
356 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
357 PARPORT_CONTROL_INIT);
359 parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
360 PARPORT_CONTROL_SELECT);
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);
368 static void bpck6_wr_extout(struct pi_adapter *pi, u8 regdata)
370 bpck6_send_cmd(pi, REG_VERSION | ACCESS_REG | ACCESS_WRITE);
371 bpck6_wr_data_byte(pi, (u8)((regdata & 0x03) << 6));
374 static void bpck6_connect(struct pi_adapter *pi)
376 dev_dbg(&pi->dev, "connect\n");
379 bpck6_wr_extout(pi, 0x3);
382 static void bpck6_disconnect(struct pi_adapter *pi)
384 dev_dbg(&pi->dev, "disconnect\n");
385 bpck6_wr_extout(pi, 0x0);
389 static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */
391 dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
392 pi->pardev->port->modes, pi->pardev->port->base);
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)
399 return 1; /* Just flat SPP */
402 static int bpck6_probe_unit(struct pi_adapter *pi)
406 dev_dbg(&pi->dev, "PROBE UNIT %x on port:%x\n", pi->unit, pi->port);
408 saved_mode = pi->mode;
409 /*LOWER DOWN TO UNIDIRECTIONAL*/
412 out = bpck6_open(pi);
414 dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
419 dev_dbg(&pi->dev, "leaving probe\n");
420 pi->mode = saved_mode;
425 dev_dbg(&pi->dev, "Failed open\n");
426 pi->mode = saved_mode;
431 static void bpck6_log_adapter(struct pi_adapter *pi)
433 char *mode_string[5]=
434 {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
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);
440 static struct pi_protocol bpck6 = {
441 .owner = THIS_MODULE,
444 .epp_first = 2, /* 2-5 use epp (need 8 ports) */
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,
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);