11da177e4SLinus Torvalds /* Low-level parallel port routines for the Multiface 3 card 21da177e4SLinus Torvalds * 31da177e4SLinus Torvalds * Author: Joerg Dorchain <joerg@dorchain.net> 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * (C) The elitist m68k Users(TM) 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * based on the existing parport_amiga and lp_mfc 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * From the MFC3 documentation: 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Miscellaneous PIA Details 131da177e4SLinus Torvalds * ------------------------- 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * The two open-drain interrupt outputs /IRQA and /IRQB are routed to 161da177e4SLinus Torvalds * /INT2 of the Z2 bus. 171da177e4SLinus Torvalds * 181da177e4SLinus Torvalds * The CPU data bus of the PIA (D0-D7) is connected to D8-D15 on the Z2 191da177e4SLinus Torvalds * bus. This means that any PIA registers are accessed at even addresses. 201da177e4SLinus Torvalds * 211da177e4SLinus Torvalds * Centronics Pin Connections for the PIA 221da177e4SLinus Torvalds * -------------------------------------- 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * The following table shows the connections between the PIA and the 251da177e4SLinus Torvalds * Centronics interface connector. These connections implement a single, but 261da177e4SLinus Torvalds * very complete, Centronics type interface. The Pin column gives the pin 271da177e4SLinus Torvalds * numbers of the PIA. The Centronics pin numbers can be found in the section 281da177e4SLinus Torvalds * "Parallel Connectors". 291da177e4SLinus Torvalds * 301da177e4SLinus Torvalds * 311da177e4SLinus Torvalds * Pin | PIA | Dir | Centronics Names 321da177e4SLinus Torvalds * -------+-----+-----+--------------------------------------------------------- 331da177e4SLinus Torvalds * 19 | CB2 | --> | /STROBE (aka /DRDY) 341da177e4SLinus Torvalds * 10-17 | PBx | <-> | DATA0 - DATA7 351da177e4SLinus Torvalds * 18 | CB1 | <-- | /ACK 361da177e4SLinus Torvalds * 40 | CA1 | <-- | BUSY 371da177e4SLinus Torvalds * 3 | PA1 | <-- | PAPER-OUT (aka POUT) 381da177e4SLinus Torvalds * 4 | PA2 | <-- | SELECTED (aka SEL) 391da177e4SLinus Torvalds * 9 | PA7 | --> | /INIT (aka /RESET or /INPUT-PRIME) 401da177e4SLinus Torvalds * 6 | PA4 | <-- | /ERROR (aka /FAULT) 411da177e4SLinus Torvalds * 7 | PA5 | --> | DIR (aka /SELECT-IN) 421da177e4SLinus Torvalds * 8 | PA6 | --> | /AUTO-FEED-XT 431da177e4SLinus Torvalds * 39 | CA2 | --> | open 441da177e4SLinus Torvalds * 5 | PA3 | <-- | /ACK (same as CB1!) 451da177e4SLinus Torvalds * 2 | PA0 | <-- | BUSY (same as CA1!) 461da177e4SLinus Torvalds * -------+-----+-----+--------------------------------------------------------- 471da177e4SLinus Torvalds * 481da177e4SLinus Torvalds * Should be enough to understand some of the driver. 491da177e4SLinus Torvalds * 501da177e4SLinus Torvalds * Per convention for normal use the port registers are visible. 511da177e4SLinus Torvalds * If you need the data direction registers, restore the value in the 521da177e4SLinus Torvalds * control register. 531da177e4SLinus Torvalds */ 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #include "multiface.h" 561da177e4SLinus Torvalds #include <linux/module.h> 571da177e4SLinus Torvalds #include <linux/init.h> 581da177e4SLinus Torvalds #include <linux/parport.h> 591da177e4SLinus Torvalds #include <linux/delay.h> 601da177e4SLinus Torvalds #include <linux/mc6821.h> 611da177e4SLinus Torvalds #include <linux/zorro.h> 621da177e4SLinus Torvalds #include <linux/interrupt.h> 631da177e4SLinus Torvalds #include <asm/setup.h> 641da177e4SLinus Torvalds #include <asm/amigahw.h> 651da177e4SLinus Torvalds #include <asm/irq.h> 661da177e4SLinus Torvalds #include <asm/amigaints.h> 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds /* Maximum Number of Cards supported */ 691da177e4SLinus Torvalds #define MAX_MFC 5 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds #undef DEBUG 721da177e4SLinus Torvalds #ifdef DEBUG 731da177e4SLinus Torvalds #define DPRINTK printk 741da177e4SLinus Torvalds #else 751da177e4SLinus Torvalds static inline int DPRINTK(void *nothing, ...) {return 0;} 761da177e4SLinus Torvalds #endif 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds static struct parport *this_port[MAX_MFC] = {NULL, }; 791da177e4SLinus Torvalds static volatile int dummy; /* for trigger readds */ 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds #define pia(dev) ((struct pia *)(dev->base)) 821da177e4SLinus Torvalds static struct parport_operations pp_mfc3_ops; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds static void mfc3_write_data(struct parport *p, unsigned char data) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "write_data %c\n",data); 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds dummy = pia(p)->pprb; /* clears irq bit */ 891da177e4SLinus Torvalds /* Triggers also /STROBE.*/ 901da177e4SLinus Torvalds pia(p)->pprb = data; 911da177e4SLinus Torvalds } 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds static unsigned char mfc3_read_data(struct parport *p) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds /* clears interrupt bit. Triggers also /STROBE. */ 961da177e4SLinus Torvalds return pia(p)->pprb; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds static unsigned char control_pc_to_mfc3(unsigned char control) 1001da177e4SLinus Torvalds { 1011da177e4SLinus Torvalds unsigned char ret = 32|64; 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */ 1041da177e4SLinus Torvalds ret &= ~32; /* /SELECT_IN */ 1051da177e4SLinus Torvalds if (control & PARPORT_CONTROL_INIT) /* INITP */ 1061da177e4SLinus Torvalds ret |= 128; 1071da177e4SLinus Torvalds if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */ 1081da177e4SLinus Torvalds ret &= ~64; 1091da177e4SLinus Torvalds if (control & PARPORT_CONTROL_STROBE) /* Strobe */ 1101da177e4SLinus Torvalds /* Handled directly by hardware */; 1111da177e4SLinus Torvalds return ret; 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds static unsigned char control_mfc3_to_pc(unsigned char control) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds unsigned char ret = PARPORT_CONTROL_STROBE 1171da177e4SLinus Torvalds | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT; 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds if (control & 128) /* /INITP */ 1201da177e4SLinus Torvalds ret |= PARPORT_CONTROL_INIT; 1211da177e4SLinus Torvalds if (control & 64) /* /AUTOLF */ 1221da177e4SLinus Torvalds ret &= ~PARPORT_CONTROL_AUTOFD; 1231da177e4SLinus Torvalds if (control & 32) /* /SELECT_IN */ 1241da177e4SLinus Torvalds ret &= ~PARPORT_CONTROL_SELECT; 1251da177e4SLinus Torvalds return ret; 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds static void mfc3_write_control(struct parport *p, unsigned char control) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "write_control %02x\n",control); 1311da177e4SLinus Torvalds pia(p)->ppra = (pia(p)->ppra & 0x1f) | control_pc_to_mfc3(control); 1321da177e4SLinus Torvalds } 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds static unsigned char mfc3_read_control( struct parport *p) 1351da177e4SLinus Torvalds { 1361da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "read_control \n"); 1371da177e4SLinus Torvalds return control_mfc3_to_pc(pia(p)->ppra & 0xe0); 1381da177e4SLinus Torvalds } 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds static unsigned char mfc3_frob_control( struct parport *p, unsigned char mask, unsigned char val) 1411da177e4SLinus Torvalds { 1421da177e4SLinus Torvalds unsigned char old; 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val); 1451da177e4SLinus Torvalds old = mfc3_read_control(p); 1461da177e4SLinus Torvalds mfc3_write_control(p, (old & ~mask) ^ val); 1471da177e4SLinus Torvalds return old; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds #if 0 /* currently unused */ 1511da177e4SLinus Torvalds static unsigned char status_pc_to_mfc3(unsigned char status) 1521da177e4SLinus Torvalds { 1531da177e4SLinus Torvalds unsigned char ret = 1; 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds if (status & PARPORT_STATUS_BUSY) /* Busy */ 1561da177e4SLinus Torvalds ret &= ~1; 1571da177e4SLinus Torvalds if (status & PARPORT_STATUS_ACK) /* Ack */ 1581da177e4SLinus Torvalds ret |= 8; 1591da177e4SLinus Torvalds if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */ 1601da177e4SLinus Torvalds ret |= 2; 1611da177e4SLinus Torvalds if (status & PARPORT_STATUS_SELECT) /* select */ 1621da177e4SLinus Torvalds ret |= 4; 1631da177e4SLinus Torvalds if (status & PARPORT_STATUS_ERROR) /* error */ 1641da177e4SLinus Torvalds ret |= 16; 1651da177e4SLinus Torvalds return ret; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds #endif 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds static unsigned char status_mfc3_to_pc(unsigned char status) 1701da177e4SLinus Torvalds { 1711da177e4SLinus Torvalds unsigned char ret = PARPORT_STATUS_BUSY; 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds if (status & 1) /* Busy */ 1741da177e4SLinus Torvalds ret &= ~PARPORT_STATUS_BUSY; 1751da177e4SLinus Torvalds if (status & 2) /* PaperOut */ 1761da177e4SLinus Torvalds ret |= PARPORT_STATUS_PAPEROUT; 1771da177e4SLinus Torvalds if (status & 4) /* Selected */ 1781da177e4SLinus Torvalds ret |= PARPORT_STATUS_SELECT; 1791da177e4SLinus Torvalds if (status & 8) /* Ack */ 1801da177e4SLinus Torvalds ret |= PARPORT_STATUS_ACK; 1811da177e4SLinus Torvalds if (status & 16) /* /ERROR */ 1821da177e4SLinus Torvalds ret |= PARPORT_STATUS_ERROR; 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds return ret; 1851da177e4SLinus Torvalds } 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds #if 0 /* currently unused */ 1881da177e4SLinus Torvalds static void mfc3_write_status( struct parport *p, unsigned char status) 1891da177e4SLinus Torvalds { 1901da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "write_status %02x\n",status); 1911da177e4SLinus Torvalds pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status); 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds #endif 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds static unsigned char mfc3_read_status(struct parport *p) 1961da177e4SLinus Torvalds { 1971da177e4SLinus Torvalds unsigned char status; 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds status = status_mfc3_to_pc(pia(p)->ppra & 0x1f); 2001da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "read_status %02x\n", status); 2011da177e4SLinus Torvalds return status; 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds #if 0 /* currently unused */ 2051da177e4SLinus Torvalds static void mfc3_change_mode( struct parport *p, int m) 2061da177e4SLinus Torvalds { 2071da177e4SLinus Torvalds /* XXX: This port only has one mode, and I am 2081da177e4SLinus Torvalds not sure about the corresponding PC-style mode*/ 2091da177e4SLinus Torvalds } 2101da177e4SLinus Torvalds #endif 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds static int use_cnt = 0; 2131da177e4SLinus Torvalds 2147d12e780SDavid Howells static irqreturn_t mfc3_interrupt(int irq, void *dev_id) 2151da177e4SLinus Torvalds { 2161da177e4SLinus Torvalds int i; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds for( i = 0; i < MAX_MFC; i++) 2191da177e4SLinus Torvalds if (this_port[i] != NULL) 2201da177e4SLinus Torvalds if (pia(this_port[i])->crb & 128) { /* Board caused interrupt */ 2211da177e4SLinus Torvalds dummy = pia(this_port[i])->pprb; /* clear irq bit */ 222f230d101SJeff Garzik parport_generic_irq(this_port[i]); 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds return IRQ_HANDLED; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds static void mfc3_enable_irq(struct parport *p) 2281da177e4SLinus Torvalds { 2291da177e4SLinus Torvalds pia(p)->crb |= PIA_C1_ENABLE_IRQ; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds static void mfc3_disable_irq(struct parport *p) 2331da177e4SLinus Torvalds { 2341da177e4SLinus Torvalds pia(p)->crb &= ~PIA_C1_ENABLE_IRQ; 2351da177e4SLinus Torvalds } 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds static void mfc3_data_forward(struct parport *p) 2381da177e4SLinus Torvalds { 2391da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "forward\n"); 2401da177e4SLinus Torvalds pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */ 2411da177e4SLinus Torvalds pia(p)->pddrb = 255; /* all pins output */ 2421da177e4SLinus Torvalds pia(p)->crb |= PIA_DDR; /* make data register visible - default */ 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds static void mfc3_data_reverse(struct parport *p) 2461da177e4SLinus Torvalds { 2471da177e4SLinus Torvalds DPRINTK(KERN_DEBUG "reverse\n"); 2481da177e4SLinus Torvalds pia(p)->crb &= ~PIA_DDR; /* make data direction register visible */ 2491da177e4SLinus Torvalds pia(p)->pddrb = 0; /* all pins input */ 2501da177e4SLinus Torvalds pia(p)->crb |= PIA_DDR; /* make data register visible - default */ 2511da177e4SLinus Torvalds } 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds static void mfc3_init_state(struct pardevice *dev, struct parport_state *s) 2541da177e4SLinus Torvalds { 2551da177e4SLinus Torvalds s->u.amiga.data = 0; 2561da177e4SLinus Torvalds s->u.amiga.datadir = 255; 2571da177e4SLinus Torvalds s->u.amiga.status = 0; 2581da177e4SLinus Torvalds s->u.amiga.statusdir = 0xe0; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds static void mfc3_save_state(struct parport *p, struct parport_state *s) 2621da177e4SLinus Torvalds { 2631da177e4SLinus Torvalds s->u.amiga.data = pia(p)->pprb; 2641da177e4SLinus Torvalds pia(p)->crb &= ~PIA_DDR; 2651da177e4SLinus Torvalds s->u.amiga.datadir = pia(p)->pddrb; 2661da177e4SLinus Torvalds pia(p)->crb |= PIA_DDR; 2671da177e4SLinus Torvalds s->u.amiga.status = pia(p)->ppra; 2681da177e4SLinus Torvalds pia(p)->cra &= ~PIA_DDR; 2691da177e4SLinus Torvalds s->u.amiga.statusdir = pia(p)->pddrb; 2701da177e4SLinus Torvalds pia(p)->cra |= PIA_DDR; 2711da177e4SLinus Torvalds } 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds static void mfc3_restore_state(struct parport *p, struct parport_state *s) 2741da177e4SLinus Torvalds { 2751da177e4SLinus Torvalds pia(p)->pprb = s->u.amiga.data; 2761da177e4SLinus Torvalds pia(p)->crb &= ~PIA_DDR; 2771da177e4SLinus Torvalds pia(p)->pddrb = s->u.amiga.datadir; 2781da177e4SLinus Torvalds pia(p)->crb |= PIA_DDR; 2791da177e4SLinus Torvalds pia(p)->ppra = s->u.amiga.status; 2801da177e4SLinus Torvalds pia(p)->cra &= ~PIA_DDR; 2811da177e4SLinus Torvalds pia(p)->pddrb = s->u.amiga.statusdir; 2821da177e4SLinus Torvalds pia(p)->cra |= PIA_DDR; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds static struct parport_operations pp_mfc3_ops = { 2861da177e4SLinus Torvalds .write_data = mfc3_write_data, 2871da177e4SLinus Torvalds .read_data = mfc3_read_data, 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds .write_control = mfc3_write_control, 2901da177e4SLinus Torvalds .read_control = mfc3_read_control, 2911da177e4SLinus Torvalds .frob_control = mfc3_frob_control, 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds .read_status = mfc3_read_status, 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds .enable_irq = mfc3_enable_irq, 2961da177e4SLinus Torvalds .disable_irq = mfc3_disable_irq, 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds .data_forward = mfc3_data_forward, 2991da177e4SLinus Torvalds .data_reverse = mfc3_data_reverse, 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds .init_state = mfc3_init_state, 3021da177e4SLinus Torvalds .save_state = mfc3_save_state, 3031da177e4SLinus Torvalds .restore_state = mfc3_restore_state, 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds .epp_write_data = parport_ieee1284_epp_write_data, 3061da177e4SLinus Torvalds .epp_read_data = parport_ieee1284_epp_read_data, 3071da177e4SLinus Torvalds .epp_write_addr = parport_ieee1284_epp_write_addr, 3081da177e4SLinus Torvalds .epp_read_addr = parport_ieee1284_epp_read_addr, 3091da177e4SLinus Torvalds 3101da177e4SLinus Torvalds .ecp_write_data = parport_ieee1284_ecp_write_data, 3111da177e4SLinus Torvalds .ecp_read_data = parport_ieee1284_ecp_read_data, 3121da177e4SLinus Torvalds .ecp_write_addr = parport_ieee1284_ecp_write_addr, 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds .compat_write_data = parport_ieee1284_write_compat, 3151da177e4SLinus Torvalds .nibble_read_data = parport_ieee1284_read_nibble, 3161da177e4SLinus Torvalds .byte_read_data = parport_ieee1284_read_byte, 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds .owner = THIS_MODULE, 3191da177e4SLinus Torvalds }; 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds /* ----------- Initialisation code --------------------------------- */ 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds static int __init parport_mfc3_init(void) 3241da177e4SLinus Torvalds { 3251da177e4SLinus Torvalds struct parport *p; 3261da177e4SLinus Torvalds int pias = 0; 3271da177e4SLinus Torvalds struct pia *pp; 3281da177e4SLinus Torvalds struct zorro_dev *z = NULL; 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds if (!MACH_IS_AMIGA) 3311da177e4SLinus Torvalds return -ENODEV; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds while ((z = zorro_find_device(ZORRO_PROD_BSC_MULTIFACE_III, z))) { 3341da177e4SLinus Torvalds unsigned long piabase = z->resource.start+PIABASE; 3351da177e4SLinus Torvalds if (!request_mem_region(piabase, sizeof(struct pia), "PIA")) 3361da177e4SLinus Torvalds continue; 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds pp = (struct pia *)ZTWO_VADDR(piabase); 3391da177e4SLinus Torvalds pp->crb = 0; 3401da177e4SLinus Torvalds pp->pddrb = 255; /* all data pins output */ 3411da177e4SLinus Torvalds pp->crb = PIA_DDR|32|8; 3421da177e4SLinus Torvalds dummy = pp->pddrb; /* reading clears interrupt */ 3431da177e4SLinus Torvalds pp->cra = 0; 3441da177e4SLinus Torvalds pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */ 3451da177e4SLinus Torvalds pp->cra = PIA_DDR; 3461da177e4SLinus Torvalds pp->ppra = 0; /* reset printer */ 3471da177e4SLinus Torvalds udelay(10); 3481da177e4SLinus Torvalds pp->ppra = 128; 3491da177e4SLinus Torvalds p = parport_register_port((unsigned long)pp, IRQ_AMIGA_PORTS, 3501da177e4SLinus Torvalds PARPORT_DMA_NONE, &pp_mfc3_ops); 3511da177e4SLinus Torvalds if (!p) 3521da177e4SLinus Torvalds goto out_port; 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds if (p->irq != PARPORT_IRQ_NONE) { 3551da177e4SLinus Torvalds if (use_cnt++ == 0) 356dace1453SThomas Gleixner if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, IRQF_SHARED, p->name, &pp_mfc3_ops)) 3571da177e4SLinus Torvalds goto out_irq; 3581da177e4SLinus Torvalds } 359c15a3837SDavid Brownell p->dev = &z->dev; 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds this_port[pias++] = p; 3621da177e4SLinus Torvalds printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); 3631da177e4SLinus Torvalds /* XXX: set operating mode */ 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds p->private_data = (void *)piabase; 3661da177e4SLinus Torvalds parport_announce_port (p); 3671da177e4SLinus Torvalds 3681da177e4SLinus Torvalds if (pias >= MAX_MFC) 3691da177e4SLinus Torvalds break; 3701da177e4SLinus Torvalds continue; 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds out_irq: 3731da177e4SLinus Torvalds parport_put_port(p); 3741da177e4SLinus Torvalds out_port: 3751da177e4SLinus Torvalds release_mem_region(piabase, sizeof(struct pia)); 3761da177e4SLinus Torvalds } 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds return pias ? 0 : -ENODEV; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds static void __exit parport_mfc3_exit(void) 3821da177e4SLinus Torvalds { 3831da177e4SLinus Torvalds int i; 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds for (i = 0; i < MAX_MFC; i++) { 3861da177e4SLinus Torvalds if (!this_port[i]) 3871da177e4SLinus Torvalds continue; 3881da177e4SLinus Torvalds parport_remove_port(this_port[i]); 38949966baeSRoel Kluin if (this_port[i]->irq != PARPORT_IRQ_NONE) { 3901da177e4SLinus Torvalds if (--use_cnt == 0) 3911da177e4SLinus Torvalds free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); 3921da177e4SLinus Torvalds } 3931da177e4SLinus Torvalds release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia)); 3941da177e4SLinus Torvalds parport_put_port(this_port[i]); 3951da177e4SLinus Torvalds } 3961da177e4SLinus Torvalds } 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); 4001da177e4SLinus Torvalds MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port"); 4011da177e4SLinus Torvalds MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port"); 4021da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds module_init(parport_mfc3_init) 4051da177e4SLinus Torvalds module_exit(parport_mfc3_exit) 406