1 /*
2  * Parallel port driver for ETRAX.
3  *
4  * NOTE!
5  *   Since par0 shares DMA with ser2 and par 1 shares DMA with ser3
6  *   this should be handled if both are enabled at the same time.
7  *   THIS IS NOT HANDLED YET!
8  *
9  * Copyright (c) 2001, 2002, 2003 Axis Communications AB
10  *
11  * Author: Fredrik Hugosson
12  *
13  */
14 
15 
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/parport.h>
19 #include <linux/ioport.h>
20 #include <linux/config.h>
21 #include <linux/errno.h>
22 #include <linux/kernel.h>
23 #include <linux/major.h>
24 #include <linux/sched.h>
25 
26 #include <linux/slab.h>
27 #include <linux/interrupt.h>
28 
29 #include <asm/setup.h>
30 #include <asm/irq.h>
31 #include <asm/io.h>
32 
33 #include <asm/segment.h>
34 #include <asm/system.h>
35 
36 #include <asm/svinto.h>
37 
38 
39 #undef DEBUG
40 #ifdef DEBUG
41 #define DPRINTK printk
42 #else
DPRINTK(void * nothing,...)43 static inline int DPRINTK(void *nothing, ...) {return 0;}
44 #endif
45 
46 /*
47  * Etrax100 DMAchannels:
48  * Par0 out : DMA2
49  * Par0 in  : DMA3
50  * Par1 out : DMA4
51  * Par1 in  : DMA5
52  * NOTE! par0 is shared with ser2 and par1 is shared with ser3 regarding
53  *       DMA and DMA irq
54  */
55 
56 //#define CONFIG_PAR0_INT 1
57 //#define CONFIG_PAR1_INT 1
58 
59 /* Define some macros to access ETRAX 100 registers */
60 #define SETF(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
61 					  IO_FIELD_(reg##_, field##_, val)
62 #define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \
63 					  IO_STATE_(reg##_, field##_, _##val)
64 
65 struct etrax100par_struct {
66 	/* parallell port control */
67 	volatile u32 *reg_ctrl_data; /* R_PARx_CTRL_DATA */
68 	const volatile u32 *reg_status_data; /* R_PARx_STATUS_DATA */
69 	volatile u32 *reg_config; /* R_PARx_CONFIG */
70 	volatile u32 *reg_delay; /* R_PARx_DELAY */
71 
72 	/* DMA control */
73 	int odma;
74 	unsigned long dma_irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */
75 
76 	volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */
77 	volatile u32 *ofirstadr;   /* adr to R_DMA_CHx_FIRST, output */
78 	volatile char *ocmdadr;     /* adr to R_DMA_CHx_CMD, output */
79 
80 	volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */
81 	volatile u32 *ifirstadr;   /* adr to R_DMA_CHx_FIRST, input */
82 	volatile char *icmdadr;     /* adr to R_DMA_CHx_CMD, input */
83 
84 	/* Non DMA interrupt stuff */
85 	unsigned long int_irq; /* R_VECT_MASK_RD */
86 	const volatile u32 *irq_mask_rd; /* R_IRQ_MASKX_RD */
87 	volatile u32 *irq_mask_clr; /* R_IRQ_MASKX_RD */
88 	const volatile u32 *irq_read; /* R_IRQ_READX */
89 	volatile u32 *irq_mask_set; /* R_IRQ_MASKX_SET */
90 	unsigned long irq_mask_tx;  /* bitmask in R_IRQ_ for tx (ready) int */
91 	unsigned long irq_mask_rx;  /* bitmask in R_IRQ_ for rx (data) int */
92 	unsigned long irq_mask_ecp_cmd;  /* mask in R_IRQ_ for ecp_cmd int */
93 	unsigned long irq_mask_peri;  /* bitmask in R_IRQ_ for peri int */
94 	int portnr;
95 
96 	/* ----- end of fields initialised in port_table[] below ----- */
97 
98 	struct parport *port;
99 
100 	/* Shadow registers */
101 	volatile unsigned long reg_ctrl_data_shadow; /* for R_PARx_CTRL_DATA */
102 	volatile unsigned long reg_config_shadow;    /* for R_PARx_CONFIG */
103 	volatile unsigned long reg_delay_shadow;    /* for R_PARx_DELAY */
104 };
105 
106 /* Always have the complete structs here, even if the port is not used!
107  *  (that way we can index this by the port number)
108  */
109 static struct etrax100par_struct port_table[] = {
110 	{
111 		R_PAR0_CTRL_DATA,
112 		R_PAR0_STATUS_DATA,
113 		R_PAR0_CONFIG,
114 		R_PAR0_DELAY,
115 		/* DMA interrupt stuff */
116 		2,
117 		1U << 4, /* uses DMA 2 and 3 */
118 		R_DMA_CH2_CLR_INTR,
119 		R_DMA_CH2_FIRST,
120 		R_DMA_CH2_CMD,
121 		R_DMA_CH3_CLR_INTR,
122 		R_DMA_CH3_FIRST,
123 		R_DMA_CH3_CMD,
124 		/* Non DMA interrupt stuff */
125 		IO_BITNR(R_VECT_MASK_RD, par0),
126 		R_IRQ_MASK0_RD,
127 		R_IRQ_MASK0_CLR,
128 		R_IRQ_READ0,
129 		R_IRQ_MASK0_SET,
130 		IO_FIELD(R_IRQ_MASK0_RD, par0_ready, 1U), /* tx (ready)*/
131 		IO_FIELD(R_IRQ_MASK0_RD, par0_data, 1U), /* rx (data)*/
132 		IO_FIELD(R_IRQ_MASK0_RD, par0_ecp_cmd, 1U), /* ecp_cmd */
133 		IO_FIELD(R_IRQ_MASK0_RD, par0_peri, 1U), /* peri */
134 		0
135 	},
136 	{
137 		R_PAR1_CTRL_DATA,
138 		R_PAR1_STATUS_DATA,
139 		R_PAR1_CONFIG,
140 		R_PAR1_DELAY,
141 		/* DMA interrupt stuff */
142 		4,
143 		1U << 8, /* uses DMA 4 and 5 */
144 
145 		R_DMA_CH4_CLR_INTR,
146 		R_DMA_CH4_FIRST,
147 		R_DMA_CH4_CMD,
148 		R_DMA_CH5_CLR_INTR,
149 		R_DMA_CH5_FIRST,
150 		R_DMA_CH5_CMD,
151 		/* Non DMA interrupt stuff */
152 		IO_BITNR(R_VECT_MASK_RD, par1),
153 		R_IRQ_MASK1_RD,
154 		R_IRQ_MASK1_CLR,
155 		R_IRQ_READ1,
156 		R_IRQ_MASK1_SET,
157 		IO_FIELD(R_IRQ_MASK1_RD, par1_ready, 1U), /* tx (ready)*/
158 		IO_FIELD(R_IRQ_MASK1_RD, par1_data, 1U), /* rx (data)*/
159 		IO_FIELD(R_IRQ_MASK1_RD, par1_ecp_cmd, 1U), /* ecp_cmd */
160 		IO_FIELD(R_IRQ_MASK1_RD, par1_peri, 1U), /* peri */
161 		1
162 	}
163 };
164 
165 
166 #define NR_PORTS (sizeof(port_table)/sizeof(struct etrax100par_struct))
167 
168 static void
parport_etrax_write_data(struct parport * p,unsigned char value)169 parport_etrax_write_data(struct parport *p, unsigned char value)
170 {
171 	struct etrax100par_struct *info =
172 		(struct etrax100par_struct *)p->private_data;
173 
174 	DPRINTK("* E100 PP %d: etrax_write_data %02X\n", p->portnum, value);
175 	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, data, value);
176 	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
177 }
178 
179 
180 static unsigned char
parport_etrax_read_data(struct parport * p)181 parport_etrax_read_data(struct parport *p)
182 {
183 	unsigned char ret;
184 	struct etrax100par_struct *info =
185 		(struct etrax100par_struct *)p->private_data;
186 
187 	ret = IO_EXTRACT(R_PAR0_STATUS_DATA, data, *info->reg_status_data);
188 
189 	DPRINTK("* E100 PP %d: etrax_read_data %02X\n", p->portnum, ret);
190 	return ret;
191 }
192 
193 
194 static void
parport_etrax_write_control(struct parport * p,unsigned char control)195 parport_etrax_write_control(struct parport *p, unsigned char control)
196 {
197 	struct etrax100par_struct *info =
198 		(struct etrax100par_struct *)p->private_data;
199 
200 	DPRINTK("* E100 PP %d: etrax_write_control %02x\n", p->portnum, control);
201 
202 	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, strb,
203 	     (control & PARPORT_CONTROL_STROBE) > 0);
204 	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, autofd,
205 	     (control & PARPORT_CONTROL_AUTOFD) > 0);
206 	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, init,
207 	     (control & PARPORT_CONTROL_INIT) == 0);
208 	SETF(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, seli,
209 	     (control & PARPORT_CONTROL_SELECT) > 0);
210 
211 	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
212 }
213 
214 
215 static unsigned char
parport_etrax_read_control(struct parport * p)216 parport_etrax_read_control( struct parport *p)
217 {
218 	unsigned char ret = 0;
219 	struct etrax100par_struct *info =
220 		(struct etrax100par_struct *)p->private_data;
221 
222 	if (IO_EXTRACT(R_PAR0_CTRL_DATA, strb, info->reg_ctrl_data_shadow))
223 		ret |= PARPORT_CONTROL_STROBE;
224 	if (IO_EXTRACT(R_PAR0_CTRL_DATA, autofd, info->reg_ctrl_data_shadow))
225 		ret |= PARPORT_CONTROL_AUTOFD;
226 	if (!IO_EXTRACT(R_PAR0_CTRL_DATA, init, info->reg_ctrl_data_shadow))
227 		ret |= PARPORT_CONTROL_INIT;
228 	if (IO_EXTRACT(R_PAR0_CTRL_DATA, seli, info->reg_ctrl_data_shadow))
229 		ret |= PARPORT_CONTROL_SELECT;
230 
231 	DPRINTK("* E100 PP %d: etrax_read_control %02x\n", p->portnum, ret);
232 	return ret;
233 }
234 
235 
236 static unsigned char
parport_etrax_frob_control(struct parport * p,unsigned char mask,unsigned char val)237 parport_etrax_frob_control(struct parport *p, unsigned char mask,
238                            unsigned char val)
239 {
240 	unsigned char old;
241 
242 	DPRINTK("* E100 PP %d: frob_control mask %02x, value %02x\n",
243 		p->portnum, mask, val);
244 	old = parport_etrax_read_control(p);
245 	parport_etrax_write_control(p, (old & ~mask) ^ val);
246 	return old;
247 }
248 
249 
250 static unsigned char
parport_etrax_read_status(struct parport * p)251 parport_etrax_read_status(struct parport *p)
252 {
253 	unsigned char ret = 0;
254 	struct etrax100par_struct *info =
255 		(struct etrax100par_struct *)p->private_data;
256 
257 	if (IO_EXTRACT(R_PAR0_STATUS_DATA, fault, *info->reg_status_data))
258 		ret |= PARPORT_STATUS_ERROR;
259 	if (IO_EXTRACT(R_PAR0_STATUS_DATA, sel, *info->reg_status_data))
260 		ret |= PARPORT_STATUS_SELECT;
261 	if (IO_EXTRACT(R_PAR0_STATUS_DATA, perr, *info->reg_status_data))
262 		ret |= PARPORT_STATUS_PAPEROUT;
263 	if (IO_EXTRACT(R_PAR0_STATUS_DATA, ack, *info->reg_status_data))
264 		ret |= PARPORT_STATUS_ACK;
265 	if (!IO_EXTRACT(R_PAR0_STATUS_DATA, busy, *info->reg_status_data))
266 		ret |= PARPORT_STATUS_BUSY;
267 
268 	DPRINTK("* E100 PP %d: status register %04x\n",
269 		p->portnum, *info->reg_status_data);
270 	DPRINTK("* E100 PP %d: read_status %02x\n", p->portnum, ret);
271 	return ret;
272 }
273 
274 
275 static void
parport_etrax_enable_irq(struct parport * p)276 parport_etrax_enable_irq(struct parport *p)
277 {
278 	struct etrax100par_struct *info =
279 		(struct etrax100par_struct *)p->private_data;
280 	*info->irq_mask_set = info->irq_mask_tx;
281 	DPRINTK("* E100 PP %d: enable irq\n", p->portnum);
282 }
283 
284 
285 static void
parport_etrax_disable_irq(struct parport * p)286 parport_etrax_disable_irq(struct parport *p)
287 {
288 	struct etrax100par_struct *info =
289 		(struct etrax100par_struct *)p->private_data;
290 	*info->irq_mask_clr = info->irq_mask_tx;
291 	DPRINTK("* E100 PP %d: disable irq\n", p->portnum);
292 }
293 
294 
295 static void
parport_etrax_data_forward(struct parport * p)296 parport_etrax_data_forward(struct parport *p)
297 {
298 	struct etrax100par_struct *info =
299 		(struct etrax100par_struct *)p->private_data;
300 
301 	DPRINTK("* E100 PP %d: forward mode\n", p->portnum);
302 	SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, enable);
303 	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
304 }
305 
306 
307 static void
parport_etrax_data_reverse(struct parport * p)308 parport_etrax_data_reverse(struct parport *p)
309 {
310 	struct etrax100par_struct *info =
311 		(struct etrax100par_struct *)p->private_data;
312 
313 	DPRINTK("* E100 PP %d: reverse mode\n", p->portnum);
314 	SETS(info->reg_ctrl_data_shadow, R_PAR0_CTRL_DATA, oe, disable);
315 	*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
316 }
317 
318 
319 static void
parport_etrax_init_state(struct pardevice * dev,struct parport_state * s)320 parport_etrax_init_state(struct pardevice *dev, struct parport_state *s)
321 {
322 	DPRINTK("* E100 PP: parport_etrax_init_state\n");
323 }
324 
325 
326 static void
parport_etrax_save_state(struct parport * p,struct parport_state * s)327 parport_etrax_save_state(struct parport *p, struct parport_state *s)
328 {
329 	DPRINTK("* E100 PP: parport_etrax_save_state\n");
330 }
331 
332 
333 static void
parport_etrax_restore_state(struct parport * p,struct parport_state * s)334 parport_etrax_restore_state(struct parport *p, struct parport_state *s)
335 {
336 	DPRINTK("* E100 PP: parport_etrax_restore_state\n");
337 }
338 
339 
340 static void
parport_etrax_inc_use_count(void)341 parport_etrax_inc_use_count(void)
342 {
343 	MOD_INC_USE_COUNT;
344 }
345 
346 
347 static void
parport_etrax_dec_use_count(void)348 parport_etrax_dec_use_count(void)
349 {
350 	MOD_DEC_USE_COUNT;
351 }
352 
353 
354 static struct
355 parport_operations pp_etrax_ops = {
356 	parport_etrax_write_data,
357 	parport_etrax_read_data,
358 
359 	parport_etrax_write_control,
360 	parport_etrax_read_control,
361 	parport_etrax_frob_control,
362 
363 	parport_etrax_read_status,
364 
365 	parport_etrax_enable_irq,
366 	parport_etrax_disable_irq,
367 
368 	parport_etrax_data_forward,
369 	parport_etrax_data_reverse,
370 
371 	parport_etrax_init_state,
372 	parport_etrax_save_state,
373 	parport_etrax_restore_state,
374 
375 	parport_etrax_inc_use_count,
376 	parport_etrax_dec_use_count,
377 
378 	parport_ieee1284_epp_write_data,
379 	parport_ieee1284_epp_read_data,
380 	parport_ieee1284_epp_write_addr,
381 	parport_ieee1284_epp_read_addr,
382 
383 	parport_ieee1284_ecp_write_data,
384 	parport_ieee1284_ecp_read_data,
385 	parport_ieee1284_ecp_write_addr,
386 
387 	parport_ieee1284_write_compat,
388 	parport_ieee1284_read_nibble,
389 	parport_ieee1284_read_byte,
390 };
391 
392 
393 static void
parport_etrax_interrupt(int irq,void * dev_id,struct pt_regs * regs)394 parport_etrax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
395 {
396 	struct etrax100par_struct *info = (struct etrax100par_struct *)
397 		((struct parport *)dev_id)->private_data;
398 	DPRINTK("* E100 PP %d: Interrupt received\n",
399 		((struct parport *)dev_id)->portnum);
400 	*info->irq_mask_clr = info->irq_mask_tx;
401 	parport_generic_irq(irq, (struct parport *)dev_id, regs);
402 }
403 
404 /* ----------- Initialisation code --------------------------------- */
405 
406 static void __init
parport_etrax_show_parallel_version(void)407 parport_etrax_show_parallel_version(void)
408 {
409 	printk("ETRAX 100LX parallel port driver v1.0, (c) 2001-2003 Axis Communications AB\n");
410 }
411 
412 #ifdef CONFIG_ETRAX_PAR0_DMA
413 #define PAR0_USE_DMA 1
414 #else
415 #define PAR0_USE_DMA 0
416 #endif
417 
418 #ifdef CONFIG_ETRAX_PAR1_DMA
419 #define PAR1_USE_DMA 1
420 #else
421 #define PAR1_USE_DMA 0
422 #endif
423 
424 static void __init
parport_etrax_init_registers(void)425 parport_etrax_init_registers(void)
426 {
427 	struct etrax100par_struct *info;
428 	int i;
429 
430 	for (i = 0, info = port_table; i < 2; i++, info++) {
431 #ifndef CONFIG_ETRAX_PARALLEL_PORT0
432 		if (i == 0)
433 			continue;
434 #endif
435 #ifndef CONFIG_ETRAX_PARALLEL_PORT1
436 		if (i == 1)
437 			continue;
438 #endif
439 		info->reg_config_shadow =
440 			IO_STATE(R_PAR0_CONFIG, iseli, inv)       |
441 			IO_STATE(R_PAR0_CONFIG, iautofd, inv)     |
442 			IO_STATE(R_PAR0_CONFIG, istrb, inv)       |
443 			IO_STATE(R_PAR0_CONFIG, iinit, inv)       |
444 			IO_STATE(R_PAR0_CONFIG, rle_in, disable)  |
445 			IO_STATE(R_PAR0_CONFIG, rle_out, disable) |
446 			IO_STATE(R_PAR0_CONFIG, enable, on)       |
447 			IO_STATE(R_PAR0_CONFIG, force, off)       |
448 			IO_STATE(R_PAR0_CONFIG, ign_ack, wait)    |
449 			IO_STATE(R_PAR0_CONFIG, oe_ack, wait_oe)  |
450 			IO_STATE(R_PAR0_CONFIG, mode, manual);
451 
452 		if ((i == 0 && PAR0_USE_DMA) || (i == 1 && PAR1_USE_DMA))
453 			info->reg_config_shadow |=
454 				IO_STATE(R_PAR0_CONFIG, dma, enable);
455 		else
456 			info->reg_config_shadow |=
457 				IO_STATE(R_PAR0_CONFIG, dma, disable);
458 
459 		*info->reg_config = info->reg_config_shadow;
460 
461 		info->reg_ctrl_data_shadow =
462 			IO_STATE(R_PAR0_CTRL_DATA, peri_int, nop)    |
463 			IO_STATE(R_PAR0_CTRL_DATA, oe, enable)       |
464 			IO_STATE(R_PAR0_CTRL_DATA, seli, inactive)   |
465 			IO_STATE(R_PAR0_CTRL_DATA, autofd, inactive) |
466 			IO_STATE(R_PAR0_CTRL_DATA, strb, inactive)   |
467 			IO_STATE(R_PAR0_CTRL_DATA, init, inactive)   |
468 			IO_STATE(R_PAR0_CTRL_DATA, ecp_cmd, data)    |
469 			IO_FIELD(R_PAR0_CTRL_DATA, data, 0);
470 		*info->reg_ctrl_data = info->reg_ctrl_data_shadow;
471 
472 		/* Clear peri int without setting shadow */
473 		*info->reg_ctrl_data = info->reg_ctrl_data_shadow |
474 			IO_STATE(R_PAR0_CTRL_DATA, peri_int, ack);
475 
476 		info->reg_delay_shadow =
477 			IO_FIELD(R_PAR0_DELAY, setup, 5)  |
478 			IO_FIELD(R_PAR0_DELAY, strobe, 5) |
479 			IO_FIELD(R_PAR0_DELAY, hold, 5);
480 		*info->reg_delay = info->reg_delay_shadow;
481 	}
482 
483 #ifdef CONFIG_ETRAX_PARALLEL_PORT0
484 #ifdef CONFIG_ETRAX_PAR0_DMA
485 	RESET_DMA(PAR0_TX_DMA_NBR);
486 	WAIT_DMA(PAR0_TX_DMA_NBR);
487 #ifdef CONFIG_ETRAX_SERIAL_PORT2
488 	printk(" Warning - DMA clash with ser2!\n");
489 #endif /* SERIAL_PORT2 */
490 #endif /* DMA */
491 #endif /* PORT0 */
492 
493 #ifdef CONFIG_ETRAX_PARALLEL_PORT1
494 #ifdef CONFIG_ETRAX_PAR1_DMA
495 	RESET_DMA(PAR1_TX_DMA_NBR);
496 	WAIT_DMA(PAR1_TX_DMA_NBR);
497 #ifdef CONFIG_ETRAX_SERIAL_PORT3
498 	printk(" Warning - DMA clash with ser3!\n");
499 #endif /* SERIAL_PORT3 */
500 #endif /* DMA */
501 #endif /* PORT1 */
502 }
503 
504 
505 int __init
parport_etrax_init(void)506 parport_etrax_init(void)
507 {
508 	struct parport *p;
509 	int port_exists = 0;
510 	int i;
511 	struct etrax100par_struct *info;
512         const char *names[] = { "parallel 0 tx+rx", "parallel 1 tx+rx" };
513 
514 	parport_etrax_show_parallel_version();
515 	parport_etrax_init_registers();
516 
517         for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
518 #ifndef CONFIG_ETRAX_PARALLEL_PORT0
519 		if (i == 0)
520 			continue;
521 #endif
522 #ifndef CONFIG_ETRAX_PARALLEL_PORT1
523 		if (i == 1)
524 			continue;
525 #endif
526                 p = parport_register_port((unsigned long)0, info->int_irq,
527                                           PARPORT_DMA_NONE, &pp_etrax_ops);
528                 if (!p)
529 			continue;
530 
531                 info->port = p;
532                 p->private_data = info;
533                 /* Axis FIXME: Set mode flags. */
534                 /* p->modes = PARPORT_MODE_TRISTATE | PARPORT_MODE_SAFEININT; */
535 
536 	        if(request_irq(info->int_irq, parport_etrax_interrupt,
537                                SA_SHIRQ, names[i], p)) {
538 	        	parport_unregister_port (p);
539                         continue;
540                 }
541 
542                 printk(KERN_INFO "%s: ETRAX 100LX port %d using irq\n",
543                        p->name, i);
544                 parport_proc_register(p);
545                 parport_announce_port(p);
546                 port_exists = 1;
547         }
548 
549 	return port_exists;
550 }
551 
552 void __exit
parport_etrax_exit(void)553 parport_etrax_exit(void)
554 {
555 	int i;
556 	struct etrax100par_struct *info;
557 
558         for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
559 #ifndef CONFIG_ETRAX_PARALLEL_PORT0
560 		if (i == 0)
561 			continue;
562 #endif
563 #ifndef CONFIG_ETRAX_PARALLEL_PORT1
564 		if (i == 1)
565 			continue;
566 #endif
567 		if (info->int_irq != PARPORT_IRQ_NONE)
568 			free_irq(info->int_irq, info->port);
569 		parport_proc_unregister(info->port);
570 		parport_unregister_port(info->port);
571         }
572 }
573