예제 #1
0
int parport_arc_init(void)
{
	/* Archimedes hardware provides only one port, at a fixed address */
	struct parport *p;

	if (check_region(PORT_BASE, 1))
		return 0;

	p = parport_register_port (PORT_BASE, IRQ_PRINTERACK,
				   PARPORT_DMA_NONE, &parport_arc_ops);

	if (!p)
		return 0;

	p->modes = PARPORT_MODE_ARCSPP;
	p->size = 1;

	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
	       p->irq);
	parport_proc_register(p);

	/* Tell the high-level drivers about the port. */
	parport_announce_port (p);

	return 1;
}
예제 #2
0
static int __init amiga_parallel_probe(struct platform_device *pdev)
{
	struct parport *p;
	int err;

	ciaa.ddrb = 0xff;
	ciab.ddra &= 0xf8;
	mb();

	p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
				   PARPORT_DMA_NONE, &pp_amiga_ops);
	if (!p)
		return -EBUSY;

	err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name,
			  p);
	if (err)
		goto out_irq;

	printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
	/* XXX: set operating mode */
	parport_announce_port(p);

	platform_set_drvdata(pdev, p);

	return 0;

out_irq:
	parport_put_port(p);
	return err;
}
예제 #3
0
static int parport_arc_init(void)
{
	/* Archimedes hardware provides only one port, at a fixed address */
	struct parport *p;
	struct resource res;
	char *fake_name = "parport probe");

	res = request_region(PORT_BASE, 1, fake_name);
	if (res == NULL)
		return 0;

	p = parport_register_port (PORT_BASE, IRQ_PRINTERACK,
				   PARPORT_DMA_NONE, &parport_arc_ops);

	if (!p) {
		release_region(PORT_BASE, 1);
		return 0;
	}

	p->modes = PARPORT_MODE_ARCSPP;
	p->size = 1;
	rename_region(res, p->name);

	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
	       p->irq);

	/* Tell the high-level drivers about the port. */
	parport_announce_port (p);

	return 1;
}
예제 #4
0
static int __init parport_mfc3_init(void)
{
	struct parport *p;
	int pias = 0;
	struct pia *pp;
	struct zorro_dev *z = NULL;

	if (!MACH_IS_AMIGA)
		return -ENODEV;

	while ((z = zorro_find_device(ZORRO_PROD_BSC_MULTIFACE_III, z))) {
		unsigned long piabase = z->resource.start+PIABASE;
		if (!request_mem_region(piabase, sizeof(struct pia), "PIA"))
			continue;

		pp = (struct pia *)ZTWO_VADDR(piabase);
		pp->crb = 0;
		pp->pddrb = 255; /* all data pins output */
		pp->crb = PIA_DDR|32|8;
		dummy = pp->pddrb; /* reading clears interrupt */
		pp->cra = 0;
		pp->pddra = 0xe0; /* /RESET,  /DIR ,/AUTO-FEED output */
		pp->cra = PIA_DDR;
		pp->ppra = 0; /* reset printer */
		udelay(10);
		pp->ppra = 128;
		p = parport_register_port((unsigned long)pp, IRQ_AMIGA_PORTS,
					  PARPORT_DMA_NONE, &pp_mfc3_ops);
		if (!p)
			goto out_port;

		if (p->irq != PARPORT_IRQ_NONE) {
			if (use_cnt++ == 0)
				if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, IRQF_SHARED, p->name, &pp_mfc3_ops))
					goto out_irq;
		}
		p->dev = &z->dev;

		this_port[pias++] = p;
		printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
		/* XXX: set operating mode */

		p->private_data = (void *)piabase;
		parport_announce_port (p);

		if (pias >= MAX_MFC)
			break;
		continue;

	out_irq:
		parport_put_port(p);
	out_port:
		release_mem_region(piabase, sizeof(struct pia));
	}

	return pias ? 0 : -ENODEV;
}
예제 #5
0
파일: daisy.c 프로젝트: xricson/knoppix
/* Clone a parport (actually, make an alias). */
static struct parport *clone_parport (struct parport *real, int muxport)
{
	struct parport *extra = parport_register_port (real->base,
						       real->irq,
						       real->dma,
						       real->ops);
	if (extra) {
		extra->portnum = real->portnum;
		extra->physport = real;
		extra->muxport = muxport;
	}

	return extra;
}
int __init
parport_etrax_init(void)
{
	struct parport *p;
	int port_exists = 0;
	int i;
	struct etrax100par_struct *info;
        const char *names[] = { "parallel 0 tx+rx", "parallel 1 tx+rx" };

	parport_etrax_show_parallel_version();
	parport_etrax_init_registers();

        for (i = 0, info = port_table; i < NR_PORTS; i++, info++) {
#ifndef CONFIG_ETRAX_PARALLEL_PORT0
		if (i == 0)
			continue;
#endif
#ifndef CONFIG_ETRAX_PARALLEL_PORT1
		if (i == 1)
			continue;
#endif
                p = parport_register_port((unsigned long)0, info->int_irq,
                                          PARPORT_DMA_NONE, &pp_etrax_ops);
                if (!p)
			continue;

                info->port = p;
                p->private_data = info;
                /* Axis FIXME: Set mode flags. */
                /* p->modes = PARPORT_MODE_TRISTATE | PARPORT_MODE_SAFEININT; */

	        if(request_irq(info->int_irq, parport_etrax_interrupt,
                               SA_SHIRQ, names[i], p)) {
	        	parport_unregister_port (p);
                        continue;
                }

                printk(KERN_INFO "%s: ETRAX 100LX port %d using irq\n",
                       p->name, i);
                parport_proc_register(p);
                parport_announce_port(p);
                port_exists = 1;
        }

	return port_exists;
}
예제 #7
0
int __init parport_amiga_init(void)
{
    struct parport *p;
    int err;

    if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL))
        return -ENODEV;

    err = -EBUSY;
    if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel"))
        goto out_mem;

    ciaa.ddrb = 0xff;
    ciab.ddra &= 0xf8;
    mb();

    p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
                              PARPORT_DMA_NONE, &pp_amiga_ops);
    if (!p)
        goto out_port;

    err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
    if (err)
        goto out_irq;

    this_port = p;
    printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
    /* XXX: set operating mode */
    parport_proc_register(p);

    parport_announce_port(p);

    return 0;

out_irq:
    parport_unregister_port(p);
out_port:
    release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100);
out_mem:
    return err;
}
예제 #8
0
static int __init parport_atari_init(void)
{
	struct parport *p;
	unsigned long flags;

	if (MACH_IS_ATARI) {
		local_irq_save(flags);
		/* Soundchip port A/B as output. */
		sound_ym.rd_data_reg_sel = 7;
		sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
		/* STROBE high. */
		sound_ym.rd_data_reg_sel = 14;
		sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
		local_irq_restore(flags);
		/* MFP port I0 as input. */
		st_mfp.data_dir &= ~1;
		/* MFP port I0 interrupt on high->low edge. */
		st_mfp.active_edge &= ~1;
		p = parport_register_port((unsigned long)&sound_ym.wd_data,
					  IRQ_MFP_BUSY, PARPORT_DMA_NONE,
					  &parport_atari_ops);
		if (!p)
			return -ENODEV;
		if (request_irq(IRQ_MFP_BUSY, parport_irq_handler, 0, p->name,
				p)) {
			parport_put_port (p);
			return -ENODEV;
		}

		this_port = p;
		printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
		parport_announce_port (p);

		return 0;
	}
	return -ENODEV;
}
예제 #9
0
__initfunc(int parport_amiga_init(void))
{
	struct parport *p;

	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) {
		ciaa.ddrb = 0xff;
		ciab.ddra &= 0xf8;
		if (!(p = parport_register_port((unsigned long)&ciaa.prb,
					IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE,
					&pp_amiga_ops)))
			return 0;
		this_port = p;
		printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
		/* XXX: set operating mode */
		parport_proc_register(p);
		p->flags |= PARPORT_FLAG_COMA;

		if (parport_probe_hook)
			(*parport_probe_hook)(p);
		return 1;

	}
	return 0;
}
예제 #10
0
int
init_one_port(struct linux_ebus_device *dev)
{
    struct parport tmpport, *p;
    unsigned long base;
    unsigned long config;
    int irq, dma;

    /* Pointer to NS87303 Configuration Registers */
    config = dev->base_address[1];

    /* Setup temporary access to Device operations */
    tmpport.base = dev->base_address[0];
    tmpport.ops = &parport_ax_ops;

    /* Configure IRQ to Push Pull, Level Low */
    /* Enable ECP mode, set bit 2 of the CTR first */
    tmpport.ops->write_control(&tmpport, 0x04);
    ns87303_modify(config, PCR,
                   PCR_EPP_ENABLE | PCR_IRQ_ODRAIN,
                   PCR_ECP_ENABLE | PCR_ECP_CLK_ENA | PCR_IRQ_POLAR);

    /* LPT CTR bit 5 controls direction of parallel port */
    ns87303_modify(config, PTR, 0, PTR_LPT_REG_DIR);

    /*
     * Now continue initializing the port
     */
    base = dev->base_address[0];
    irq = dev->irqs[0];
    dma = PARPORT_DMA_AUTO;

    if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops)))
        return 0;

    /* Save away pointer to our EBus DMA */
    p->private_data = (void *)dev->base_address[2];

    p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
    if (!check_region(p->base + 0x400, 3)) {
        p->modes |= parport_ECR_present(p);
        p->modes |= parport_ECP_supported(p);
        p->modes |= parport_ECPPS2_supported(p);
    }
    p->size = 3;

    if (p->dma == PARPORT_DMA_AUTO)
        p->dma = (p->modes & PARPORT_MODE_PCECP) ? 0 : PARPORT_DMA_NONE;

    printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
    if (p->irq != PARPORT_IRQ_NONE)
        printk(", irq %s", __irq_itoa(p->irq));
    if (p->dma != PARPORT_DMA_NONE)
        printk(", dma %d", p->dma);
    printk(" [");
    {
        int f = 0;
        printmode(SPP);
        printmode(PS2);
        printmode(ECP);
        printmode(ECPPS2);
    }
    printk("]\n");
    parport_proc_register(p);
    p->flags |= PARPORT_FLAG_COMA;

    p->ops->write_control(p, 0x0c);
    p->ops->write_data(p, 0);

    if (parport_probe_hook)
        (*parport_probe_hook)(p);

    return 1;
}
예제 #11
0
struct parport *__devinit parport_gsc_probe_port (unsigned long base,
						 unsigned long base_hi,
						 int irq, int dma,
						 struct pci_dev *dev)
{
	struct parport_gsc_private *priv;
	struct parport_operations *ops;
	struct parport tmp;
	struct parport *p = &tmp;

	priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL);
	if (!priv) {
		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
		return NULL;
	}
	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
	if (!ops) {
		printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
			base);
		kfree (priv);
		return NULL;
	}
	memcpy (ops, &parport_gsc_ops, sizeof (struct parport_operations));
	priv->ctr = 0xc;
	priv->ctr_writable = 0xff;
	priv->dma_buf = 0;
	priv->dma_handle = 0;
	priv->dev = dev;
	p->base = base;
	p->base_hi = base_hi;
	p->irq = irq;
	p->dma = dma;
	p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;
	p->ops = ops;
	p->private_data = priv;
	p->physport = p;
	if (!parport_SPP_supported (p)) {
		/* No port. */
		kfree (priv);
		return NULL;
	}
	parport_PS2_supported (p);

	if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
					PARPORT_DMA_NONE, ops))) {
		kfree (priv);
		kfree (ops);
		return NULL;
	}

	p->base_hi = base_hi;
	p->modes = tmp.modes;
	p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
	p->private_data = priv;

	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
	p->irq = irq;
	if (p->irq == PARPORT_IRQ_AUTO) {
		p->irq = PARPORT_IRQ_NONE;
	}
	if (p->irq != PARPORT_IRQ_NONE) {
		printk(", irq %d", p->irq);

		if (p->dma == PARPORT_DMA_AUTO) {
			p->dma = PARPORT_DMA_NONE;
		}
	}
	if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq
                                           is mandatory (see above) */
		p->dma = PARPORT_DMA_NONE;

	printk(" [");
#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
	{
		int f = 0;
		printmode(PCSPP);
		printmode(TRISTATE);
		printmode(COMPAT)
		printmode(EPP);
//		printmode(ECP);
//		printmode(DMA);
	}
#undef printmode
	printk("]\n");

	if (p->irq != PARPORT_IRQ_NONE) {
		if (request_irq (p->irq, parport_gsc_interrupt,
				 0, p->name, p)) {
			printk (KERN_WARNING "%s: irq %d in use, "
				"resorting to polled operation\n",
				p->name, p->irq);
			p->irq = PARPORT_IRQ_NONE;
			p->dma = PARPORT_DMA_NONE;
		}
	}

	/* Done probing.  Now put the port into a sensible start-up state. */

	parport_gsc_write_data(p, 0);
	parport_gsc_data_forward (p);

	/* Now that we've told the sharing engine about the port, and
	   found out its characteristics, let the high-level drivers
	   know about it. */
	parport_announce_port (p);

	return p;
}
예제 #12
0
static int parport_ax88796_probe(struct platform_device *pdev)
{
	struct device *_dev = &pdev->dev;
	struct ax_drvdata *dd;
	struct parport *pp = NULL;
	struct resource *res;
	unsigned long size;
	int spacing;
	int irq;
	int ret;

	dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL);
	if (dd == NULL) {
		dev_err(_dev, "no memory for private data\n");
		return -ENOMEM;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(_dev, "no MEM specified\n");
		ret = -ENXIO;
		goto exit_mem;
	}

	size = (res->end - res->start) + 1;
	spacing = size / 3;

	dd->io = request_mem_region(res->start, size, pdev->name);
	if (dd->io == NULL) {
		dev_err(_dev, "cannot reserve memory\n");
		ret = -ENXIO;
		goto exit_mem;
	}

	dd->base = ioremap(res->start, size);
	if (dd->base == NULL) {
		dev_err(_dev, "cannot ioremap region\n");
		ret = -ENXIO;
		goto exit_res;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq <= 0)
		irq = PARPORT_IRQ_NONE;

	pp = parport_register_port((unsigned long)dd->base, irq,
				   PARPORT_DMA_NONE,
				   &parport_ax88796_ops);

	if (pp == NULL) {
		dev_err(_dev, "failed to register parallel port\n");
		ret = -ENOMEM;
		goto exit_unmap;
	}

	pp->private_data = dd;
	dd->parport = pp;
	dd->dev = _dev;

	dd->spp_data = dd->base;
	dd->spp_spr  = dd->base + (spacing * 1);
	dd->spp_cpr  = dd->base + (spacing * 2);

	/* initialise the port controls */
	writeb(AX_CPR_STRB, dd->spp_cpr);

	if (irq >= 0) {
		/* request irq */
		ret = request_irq(irq, parport_irq_handler,
				  IRQF_TRIGGER_FALLING, pdev->name, pp);

		if (ret < 0)
			goto exit_port;

		dd->irq_enabled = 1;
	}

	platform_set_drvdata(pdev, pp);

	dev_info(_dev, "attached parallel port driver\n");
	parport_announce_port(pp);

	return 0;

 exit_port:
	parport_remove_port(pp);
 exit_unmap:
	iounmap(dd->base);
 exit_res:
	release_resource(dd->io);
	kfree(dd->io);
 exit_mem:
	kfree(dd);
	return ret;
}
예제 #13
0
static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match)
{
	struct parport_operations *ops;
	struct bpp_regs __iomem *regs;
	int irq, dma, err = 0, size;
	unsigned char value_tcr;
	void __iomem *base;
	struct parport *p;

	irq = op->irqs[0];
	base = of_ioremap(&op->resource[0], 0,
			  resource_size(&op->resource[0]),
			  "sunbpp");
	if (!base)
		return -ENODEV;

	size = resource_size(&op->resource[0]);
	dma = PARPORT_DMA_NONE;

	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
        if (!ops)
		goto out_unmap;

        memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations));

	dprintk(("register_port\n"));
	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
		goto out_free_ops;

	p->size = size;
	p->dev = &op->dev;

	if ((err = request_irq(p->irq, parport_irq_handler,
			       IRQF_SHARED, p->name, p)) != 0) {
		goto out_put_port;
	}

	parport_sunbpp_enable_irq(p);

	regs = (struct bpp_regs __iomem *)p->base;

	value_tcr = sbus_readb(&regs->p_tcr);
	value_tcr &= ~P_TCR_DIR;
	sbus_writeb(value_tcr, &regs->p_tcr);

	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);

	dev_set_drvdata(&op->dev, p);

	parport_announce_port(p);

	return 0;

out_put_port:
	parport_put_port(p);

out_free_ops:
	kfree(ops);

out_unmap:
	of_iounmap(&op->resource[0], base, size);

	return err;
}
static int __init init_one_port(struct sbus_dev *sdev)
{
	struct parport *p;
	/* at least in theory there may be a "we don't dma" case */
	struct parport_operations *ops;
	unsigned long base;
	int irq, dma, err, size;
	struct bpp_regs *regs;
	unsigned char value_tcr;

	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
	irq = sdev->irqs[0];
	base = sbus_ioremap(&sdev->resource[0], 0,
			    sdev->reg_addrs[0].reg_size, 
			    "sunbpp");
	size = sdev->reg_addrs[0].reg_size;
	dma = PARPORT_DMA_NONE;

	dprintk(("alloc(ppops), "));
	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
        if (!ops) {
		sbus_iounmap(base, size);
		return 0;
        }

        memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));

	dprintk(("register_port\n"));
	if (!(p = parport_register_port(base, irq, dma, ops))) {
		kfree(ops);
		sbus_iounmap(base, size);
		return 0;
	}

	p->size = size;

	dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
		p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
			       SA_SHIRQ, p->name, p)) != 0) {
		dprintk(("ERROR %d\n", err));
		parport_unregister_port(p);
		kfree(ops);
		sbus_iounmap(base, size);
		return err;
	} else {
		dprintk(("OK\n"));
		parport_sunbpp_enable_irq(p);
	}

	regs = (struct bpp_regs *)p->base;
	dprintk((KERN_DEBUG "forward\n"));
	value_tcr = sbus_readb(&regs->p_tcr);
	value_tcr &= ~P_TCR_DIR;
	sbus_writeb(value_tcr, &regs->p_tcr);

	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
	parport_proc_register(p);
	parport_announce_port (p);

	return 1;
}
예제 #15
0
static int __init init_one_port(struct sbus_dev *sdev)
{
	struct parport *p;
	/* at least in theory there may be a "we don't dma" case */
	struct parport_operations *ops;
	void __iomem *base;
	int irq, dma, err = 0, size;
	struct bpp_regs __iomem *regs;
	unsigned char value_tcr;
	Node *node;

	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
	node = kmalloc(sizeof(Node), GFP_KERNEL);
	if (!node)
		goto out0;

	irq = sdev->irqs[0];
	base = sbus_ioremap(&sdev->resource[0], 0,
			    sdev->reg_addrs[0].reg_size, 
			    "sunbpp");
	if (!base)
		goto out1;

	size = sdev->reg_addrs[0].reg_size;
	dma = PARPORT_DMA_NONE;

	dprintk(("alloc(ppops), "));
	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
        if (!ops)
		goto out2;

        memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));

	dprintk(("register_port\n"));
	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
		goto out3;

	p->size = size;

	dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
		p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
			       SA_SHIRQ, p->name, p)) != 0) {
		dprintk(("ERROR %d\n", err));
		goto out4;
	}
	dprintk(("OK\n"));
	parport_sunbpp_enable_irq(p);

	regs = (struct bpp_regs __iomem *)p->base;
	dprintk((KERN_DEBUG "forward\n"));
	value_tcr = sbus_readb(&regs->p_tcr);
	value_tcr &= ~P_TCR_DIR;
	sbus_writeb(value_tcr, &regs->p_tcr);

	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
	node->port = p;
	list_add(&node->list, &port_list);
	parport_announce_port (p);

	return 1;

out4:
	parport_put_port(p);
out3:
	kfree(ops);
out2:
	sbus_iounmap(base, size);
out1:
	kfree(node);
out0:
	return err;
}
예제 #16
0
static int __devinit init_one_port(struct sbus_dev *sdev)
{
	struct parport *p;
	/* at least in theory there may be a "we don't dma" case */
	struct parport_operations *ops;
	void __iomem *base;
	int irq, dma, err = 0, size;
	struct bpp_regs __iomem *regs;
	unsigned char value_tcr;

	irq = sdev->irqs[0];
	base = sbus_ioremap(&sdev->resource[0], 0,
			    sdev->reg_addrs[0].reg_size, 
			    "sunbpp");
	if (!base)
		return -ENODEV;

	size = sdev->reg_addrs[0].reg_size;
	dma = PARPORT_DMA_NONE;

	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
        if (!ops)
		goto out_unmap;

        memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));

	dprintk(("register_port\n"));
	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
		goto out_free_ops;

	p->size = size;
	p->dev = &sdev->ofdev.dev;

	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
			       IRQF_SHARED, p->name, p)) != 0) {
		goto out_put_port;
	}

	parport_sunbpp_enable_irq(p);

	regs = (struct bpp_regs __iomem *)p->base;

	value_tcr = sbus_readb(&regs->p_tcr);
	value_tcr &= ~P_TCR_DIR;
	sbus_writeb(value_tcr, &regs->p_tcr);

	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);

	dev_set_drvdata(&sdev->ofdev.dev, p);

	parport_announce_port(p);

	return 0;

out_put_port:
	parport_put_port(p);

out_free_ops:
	kfree(ops);

out_unmap:
	sbus_iounmap(base, size);

	return err;
}