struct resource *
ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
		       u_long start, u_long end, u_long count, u_int flags)
{
    struct ata_pci_controller *controller = device_get_softc(dev);
    int unit = ((struct ata_channel *)device_get_softc(child))->unit;
    struct resource *res = NULL;
    int myrid;

    if (type == SYS_RES_IOPORT) {
	switch (*rid) {
	case ATA_IOADDR_RID:
	    if (ata_legacy(dev)) {
		start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
		count = ATA_IOSIZE;
		end = start + count - 1;
	    }
	    myrid = PCIR_BAR(0) + (unit << 3);
	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				     SYS_RES_IOPORT, &myrid,
				     start, end, count, flags);
	    break;

	case ATA_CTLADDR_RID:
	    if (ata_legacy(dev)) {
		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET;
		count = ATA_CTLIOSIZE;
		end = start + count - 1;
	    }
	    myrid = PCIR_BAR(1) + (unit << 3);
	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				     SYS_RES_IOPORT, &myrid,
				     start, end, count, flags);
	    break;
	}
    }
    if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
	if (ata_legacy(dev)) {
	    int irq = (unit == 0 ? 14 : 15);
	    
	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
				     SYS_RES_IRQ, rid, irq, irq, 1, flags);
	}
	else
	    res = controller->r_irq;
    }
    return res;
}
int
ata_pci_attach(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    u_int32_t cmd;
    int unit;

    /* do chipset specific setups only needed once */
    if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
	ctlr->channels = 2;
    else
	ctlr->channels = 1;
    ctlr->allocate = ata_pci_allocate;
    ctlr->dmainit = ata_pci_dmainit;
    ctlr->dev = dev;

    /* if needed try to enable busmastering */
    cmd = pci_read_config(dev, PCIR_COMMAND, 2);
    if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
	pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
    }

    /* if busmastering mode "stuck" use it */
    if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
	ctlr->r_type1 = SYS_RES_IOPORT;
	ctlr->r_rid1 = ATA_BMADDR_RID;
	ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1,
					      RF_ACTIVE);
    }

    if (ctlr->chipinit(dev))
	return ENXIO;

    /* attach all channels on this controller */
    for (unit = 0; unit < ctlr->channels; unit++) {
	if ((unit == 0 || unit == 1) && ata_legacy(dev)) {
	    device_add_child(dev, "ata", unit);
	    continue;
	}
	device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 2));
    }
    bus_generic_attach(dev);
    return 0;
}
Example #3
0
int
ata_pci_attach(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    device_t child;
    u_int32_t cmd;
    int unit;

    /* do chipset specific setups only needed once */
    ctlr->legacy = ata_legacy(dev);
    if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
	ctlr->channels = 2;
    else
	ctlr->channels = 1;
    ctlr->ichannels = -1;
    ctlr->ch_attach = ata_pci_ch_attach;
    ctlr->ch_detach = ata_pci_ch_detach;
    ctlr->dev = dev;

    /* if needed try to enable busmastering */
    cmd = pci_read_config(dev, PCIR_COMMAND, 2);
    if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
	pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
	cmd = pci_read_config(dev, PCIR_COMMAND, 2);
    }

    /* if busmastering mode "stuck" use it */
    if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) {
	ctlr->r_type1 = SYS_RES_IOPORT;
	ctlr->r_rid1 = ATA_BMADDR_RID;
	ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1,
					      RF_ACTIVE);
    }

    if (ctlr->chipinit(dev))
	return ENXIO;

    /* attach all channels on this controller */
    for (unit = 0; unit < ctlr->channels; unit++) {
	if ((ctlr->ichannels & (1 << unit)) == 0)
	    continue;
	child = device_add_child(dev, "ata",
	    ((unit == 0 || unit == 1) && ctlr->legacy) ?
	    unit : devclass_find_free_unit(ata_devclass, 2));
	if (child == NULL)
	    device_printf(dev, "failed to add ata child device\n");
	else
	    device_set_ivars(child, (void *)(intptr_t)unit);
    }
    bus_generic_attach(dev);
    return 0;
}
int
ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
		      void *cookie)
{
    if (ata_legacy(dev)) {
	return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
    }
    else {
	struct ata_pci_controller *controller = device_get_softc(dev);
	int unit = ((struct ata_channel *)device_get_softc(child))->unit;

	controller->interrupt[unit].function = NULL;
	controller->interrupt[unit].argument = NULL;
	return 0;
    }
}
Example #5
0
static int
imx_ata_attach(device_t dev)
{
	struct ata_pci_controller *ctrl;
	device_t child;
	int unit;

	ctrl = device_get_softc(dev);
	/* do chipset specific setups only needed once */
	ctrl->legacy = ata_legacy(dev);
	ctrl->channels = 1;
	ctrl->ichannels = -1;
	ctrl->ch_attach = ata_pci_ch_attach;
	ctrl->ch_detach = ata_pci_ch_detach;
	ctrl->dev = dev;

	ctrl->r_type1 = SYS_RES_MEMORY;
	ctrl->r_rid1 = 0;
	ctrl->r_res1 = bus_alloc_resource_any(dev, ctrl->r_type1,
	    &ctrl->r_rid1, RF_ACTIVE);

	if (ata_setup_interrupt(dev, imx_ata_intr)) {
		device_printf(dev, "failed to setup interrupt\n");
    		return ENXIO;
	}

	ctrl->channels = 1;

	ctrl->ch_attach = imx_ata_ch_attach;
	ctrl->setmode = imx_ata_setmode;

	/* attach all channels on this controller */
	unit = 0;
	child = device_add_child(dev, "ata", ((unit == 0) && ctrl->legacy) ?
		    unit : devclass_find_free_unit(ata_devclass, 2));
	if (child == NULL)
		device_printf(dev, "failed to add ata child device\n");
	else
		device_set_ivars(child, (void *)(intptr_t)unit);

	bus_generic_attach(dev);
	return 0;
}
int
ata_pci_status(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);

    if ((dumping || !ata_legacy(device_get_parent(dev))) &&
	ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) ||
		    (ch->dma->flags & ATA_DMA_ACTIVE))) {
	int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;

	if ((bmstat & ATA_BMSTAT_INTERRUPT) == 0)
	    return 0;
	ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR);
	DELAY(1);
    }
    if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) {
	DELAY(100);
	if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY)
	    return 0;
    }
    return 1;
}
int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 
		   int flags, driver_filter_t *filter, driver_intr_t *function, 
		   void *argument, void **cookiep)
{
    if (ata_legacy(dev)) {
	return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
			      flags, filter, function, argument, cookiep);
    }
    else {
	struct ata_pci_controller *controller = device_get_softc(dev);
	int unit = ((struct ata_channel *)device_get_softc(child))->unit;

	if (filter != NULL) {
		printf("ata-pci.c: we cannot use a filter here\n");
		return (EINVAL);
	}
	controller->interrupt[unit].function = function;
	controller->interrupt[unit].argument = argument;
	*cookiep = controller;
	return 0;
    }
}
int
ata_pci_allocate(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    struct resource *io = NULL, *ctlio = NULL;
    int i, rid;

    rid = ATA_IOADDR_RID;
    if (!(io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE)))
	return ENXIO;

    rid = ATA_CTLADDR_RID;
    if (!(ctlio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,RF_ACTIVE))){
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
	return ENXIO;
    }

    for (i = ATA_DATA; i <= ATA_COMMAND; i ++) {
	ch->r_io[i].res = io;
	ch->r_io[i].offset = i;
    }
    ch->r_io[ATA_CONTROL].res = ctlio;
    ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2;
    ch->r_io[ATA_IDX_ADDR].res = io;
    ata_default_registers(dev);
    if (ctlr->r_res1) {
	for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) {
	    ch->r_io[i].res = ctlr->r_res1;
	    ch->r_io[i].offset = (i - ATA_BMCMD_PORT) + (ch->unit*ATA_BMIOSIZE);
	}
    }

    ata_pci_hw(dev);
    return 0;
}
int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
			 struct resource *r)
{
    int unit = ((struct ata_channel *)device_get_softc(child))->unit;

    if (type == SYS_RES_IOPORT) {
	switch (rid) {
	case ATA_IOADDR_RID:
	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
					SYS_RES_IOPORT,
					PCIR_BAR(0) + (unit << 3), r);
	    break;

	case ATA_CTLADDR_RID:
	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
					SYS_RES_IOPORT,
					PCIR_BAR(1) + (unit << 3), r);
	    break;
	default:
	    return ENOENT;
	}
    }
    if (type == SYS_RES_IRQ) {
	if (rid != ATA_IRQ_RID)
	    return ENOENT;

	if (ata_legacy(dev)) {
	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
					SYS_RES_IRQ, rid, r);
	}
	else  
	    return 0;
    }
    return EINVAL;
}