Date: Mon, 16 Nov 2009 15:38:27 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r199322 - in head/sys/dev: ahci ata ata/chipsets Message-ID: <200911161538.nAGFcRsS074268@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Mon Nov 16 15:38:27 2009 New Revision: 199322 URL: http://svn.freebsd.org/changeset/base/199322 Log: Change the way in which AHCI+PATA combined controllers, such as JMicron and Marvell handled. Instead of trying to attach two different drivers to single device, wrapping each call, make one of them (atajmicron, atamarvell) attach do device solely, but create child device for AHCI driver, passing it all required resources. It is quite easy, as none of resources are shared, except IRQ. As result, it: - makes drivers operation more independent and straitforward, - allows to use new ahci(4) driver with such devices, adding support for new features, such as PMP and NCQ, same time keeping legacy PATA support, - will allow to just drop old ataahci driver, when it's time come. Modified: head/sys/dev/ahci/ahci.c head/sys/dev/ahci/ahci.h head/sys/dev/ata/ata-pci.c head/sys/dev/ata/ata-pci.h head/sys/dev/ata/chipsets/ata-ahci.c head/sys/dev/ata/chipsets/ata-jmicron.c head/sys/dev/ata/chipsets/ata-marvell.c Modified: head/sys/dev/ahci/ahci.c ============================================================================== --- head/sys/dev/ahci/ahci.c Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ahci/ahci.c Mon Nov 16 15:38:27 2009 (r199322) @@ -99,7 +99,14 @@ MALLOC_DEFINE(M_AHCI, "AHCI driver", "AH static struct { uint32_t id; const char *name; - int flags; + int quirks; +#define AHCI_Q_NOFORCE 1 +#define AHCI_Q_NOPMP 2 +#define AHCI_Q_NONCQ 4 +#define AHCI_Q_1CH 8 +#define AHCI_Q_2CH 16 +#define AHCI_Q_4CH 32 +#define AHCI_Q_EDGEIS 64 } ahci_ids[] = { {0x43801002, "ATI IXP600", 0}, {0x43901002, "ATI IXP700", 0}, @@ -145,6 +152,15 @@ static struct { {0x3b2b8086, "Intel PCH", 0}, {0x3b2c8086, "Intel PCH", 0}, {0x3b2f8086, "Intel PCH", 0}, + {0x2361197b, "JMicron JMB361", AHCI_Q_NOFORCE}, + {0x2363197b, "JMicron JMB363", AHCI_Q_NOFORCE}, + {0x2365197b, "JMicron JMB365", AHCI_Q_NOFORCE}, + {0x2366197b, "JMicron JMB366", AHCI_Q_NOFORCE}, + {0x2368197b, "JMicron JMB368", AHCI_Q_NOFORCE}, + {0x611111ab, "Marvell 88SX6111", AHCI_Q_NOFORCE|AHCI_Q_1CH|AHCI_Q_EDGEIS}, + {0x612111ab, "Marvell 88SX6121", AHCI_Q_NOFORCE|AHCI_Q_2CH|AHCI_Q_EDGEIS}, + {0x614111ab, "Marvell 88SX6141", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS}, + {0x614511ab, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS}, {0x044c10de, "NVIDIA MCP65", 0}, {0x044d10de, "NVIDIA MCP65", 0}, {0x044e10de, "NVIDIA MCP65", 0}, @@ -226,9 +242,39 @@ static int ahci_probe(device_t dev) { char buf[64]; + int i, valid = 0; + uint32_t devid = pci_get_devid(dev); + + /* Is this a possible AHCI candidate? */ + if (pci_get_class(dev) == PCIC_STORAGE && + pci_get_subclass(dev) == PCIS_STORAGE_SATA && + pci_get_progif(dev) == PCIP_STORAGE_SATA_AHCI_1_0) + valid = 1; + /* Is this a known AHCI chip? */ + for (i = 0; ahci_ids[i].id != 0; i++) { + if (ahci_ids[i].id == devid && + (valid || !(ahci_ids[i].quirks & AHCI_Q_NOFORCE))) { + snprintf(buf, sizeof(buf), "%s AHCI SATA controller", + ahci_ids[i].name); + device_set_desc_copy(dev, buf); + return (BUS_PROBE_VENDOR); + } + } + if (!valid) + return (ENXIO); + device_set_desc_copy(dev, "AHCI SATA controller"); + return (BUS_PROBE_VENDOR); +} + +static int +ahci_ata_probe(device_t dev) +{ + char buf[64]; int i; uint32_t devid = pci_get_devid(dev); + if ((intptr_t)device_get_ivars(dev) >= 0) + return (ENXIO); /* Is this a known AHCI chip? */ for (i = 0; ahci_ids[i].id != 0; i++) { if (ahci_ids[i].id == devid) { @@ -238,11 +284,6 @@ ahci_probe(device_t dev) return (BUS_PROBE_VENDOR); } } - /* Is this a possible AHCI candidate? */ - if (pci_get_class(dev) != PCIC_STORAGE || - pci_get_subclass(dev) != PCIS_STORAGE_SATA || - pci_get_progif(dev) != PCIP_STORAGE_SATA_AHCI_1_0) - return (ENXIO); device_set_desc_copy(dev, "AHCI SATA controller"); return (BUS_PROBE_VENDOR); } @@ -252,10 +293,15 @@ ahci_attach(device_t dev) { struct ahci_controller *ctlr = device_get_softc(dev); device_t child; - int error, unit, speed; + int error, unit, speed, i; + uint32_t devid = pci_get_devid(dev); u_int32_t version; ctlr->dev = dev; + i = 0; + while (ahci_ids[i].id != 0 && ahci_ids[i].id != devid) + i++; + ctlr->quirks = ahci_ids[i].quirks; resource_int_value(device_get_name(dev), device_get_unit(dev), "ccc", &ctlr->ccc); /* if we have a memory BAR(5) we are likely on an AHCI part */ @@ -282,10 +328,32 @@ ahci_attach(device_t dev) rman_fini(&ctlr->sc_iomem); return (error); }; - /* Get the number of HW channels */ + /* Get the HW capabilities */ + version = ATA_INL(ctlr->r_mem, AHCI_VS); + ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP); + if (version >= 0x00010020) + ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2); ctlr->ichannels = ATA_INL(ctlr->r_mem, AHCI_PI); + if (ctlr->quirks & AHCI_Q_1CH) { + ctlr->caps &= ~AHCI_CAP_NPMASK; + ctlr->ichannels &= 0x01; + } + if (ctlr->quirks & AHCI_Q_2CH) { + ctlr->caps &= ~AHCI_CAP_NPMASK; + ctlr->caps |= 1; + ctlr->ichannels &= 0x03; + } + if (ctlr->quirks & AHCI_Q_4CH) { + ctlr->caps &= ~AHCI_CAP_NPMASK; + ctlr->caps |= 3; + ctlr->ichannels &= 0x0f; + } ctlr->channels = MAX(flsl(ctlr->ichannels), - (ATA_INL(ctlr->r_mem, AHCI_CAP) & AHCI_CAP_NPMASK) + 1); + (ctlr->caps & AHCI_CAP_NPMASK) + 1); + if (ctlr->quirks & AHCI_Q_NOPMP) + ctlr->caps &= ~AHCI_CAP_SPM; + if (ctlr->quirks & AHCI_Q_NONCQ) + ctlr->caps &= ~AHCI_CAP_SNCQ; /* Setup interrupts. */ if (ahci_setup_interrupt(dev)) { bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); @@ -293,10 +361,6 @@ ahci_attach(device_t dev) return ENXIO; } /* Announce HW capabilities. */ - version = ATA_INL(ctlr->r_mem, AHCI_VS); - ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP); - if (version >= 0x00010020) - ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2); speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT; device_printf(dev, "AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s\n", @@ -531,8 +595,15 @@ ahci_intr(void *data) for (; unit < ctlr->channels; unit++) { if ((is & (1 << unit)) != 0 && (arg = ctlr->interrupt[unit].argument)) { - ctlr->interrupt[unit].function(arg); - ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + if (ctlr->quirks & AHCI_Q_EDGEIS) { + /* Some controller have edge triggered IS. */ + ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + ctlr->interrupt[unit].function(arg); + } else { + /* but AHCI declares level triggered IS. */ + ctlr->interrupt[unit].function(arg); + ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + } } } } @@ -665,6 +736,25 @@ static driver_t ahci_driver = { sizeof(struct ahci_controller) }; DRIVER_MODULE(ahci, pci, ahci_driver, ahci_devclass, 0, 0); +static device_method_t ahci_ata_methods[] = { + DEVMETHOD(device_probe, ahci_ata_probe), + DEVMETHOD(device_attach, ahci_attach), + DEVMETHOD(device_detach, ahci_detach), + DEVMETHOD(device_suspend, ahci_suspend), + DEVMETHOD(device_resume, ahci_resume), + DEVMETHOD(bus_print_child, ahci_print_child), + DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), + DEVMETHOD(bus_release_resource, ahci_release_resource), + DEVMETHOD(bus_setup_intr, ahci_setup_intr), + DEVMETHOD(bus_teardown_intr,ahci_teardown_intr), + { 0, 0 } +}; +static driver_t ahci_ata_driver = { + "ahci", + ahci_ata_methods, + sizeof(struct ahci_controller) +}; +DRIVER_MODULE(ahci, atapci, ahci_ata_driver, ahci_devclass, 0, 0); MODULE_VERSION(ahci, 1); MODULE_DEPEND(ahci, cam, 1, 1, 1); @@ -688,6 +778,7 @@ ahci_ch_attach(device_t dev) ch->unit = (intptr_t)device_get_ivars(dev); ch->caps = ctlr->caps; ch->caps2 = ctlr->caps2; + ch->quirks = ctlr->quirks; ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1, mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF); resource_int_value(device_get_name(dev), @@ -858,7 +949,7 @@ static driver_t ahcich_driver = { ahcich_methods, sizeof(struct ahci_channel) }; -DRIVER_MODULE(ahcich, ahci, ahcich_driver, ahci_devclass, 0, 0); +DRIVER_MODULE(ahcich, ahci, ahcich_driver, ahcich_devclass, 0, 0); struct ahci_dc_cb_args { bus_addr_t maddr; Modified: head/sys/dev/ahci/ahci.h ============================================================================== --- head/sys/dev/ahci/ahci.h Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ahci/ahci.h Mon Nov 16 15:38:27 2009 (r199322) @@ -352,6 +352,7 @@ struct ahci_channel { struct cam_path *path; uint32_t caps; /* Controller capabilities */ uint32_t caps2; /* Controller capabilities */ + int quirks; int numslots; /* Number of present slots */ int pm_level; /* power management level */ int sata_rev; /* Maximum allowed SATA generation */ @@ -391,6 +392,7 @@ struct ahci_controller { } irqs[16]; uint32_t caps; /* Controller capabilities */ uint32_t caps2; /* Controller capabilities */ + int quirks; int numirqs; int channels; int ichannels; Modified: head/sys/dev/ata/ata-pci.c ============================================================================== --- head/sys/dev/ata/ata-pci.c Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ata/ata-pci.c Mon Nov 16 15:38:27 2009 (r199322) @@ -189,91 +189,138 @@ ata_pci_resume(device_t dev) return error; } +int +ata_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + + return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result)); +} + +int +ata_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + + return (BUS_WRITE_IVAR(device_get_parent(dev), dev, which, value)); +} + +uint32_t +ata_pci_read_config(device_t dev, device_t child, int reg, int width) +{ + + return (pci_read_config(dev, reg, width)); +} + +void +ata_pci_write_config(device_t dev, device_t child, int reg, + uint32_t val, int width) +{ + + pci_write_config(dev, reg, val, width); +} + 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 (controller->legacy) { - 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 (controller->legacy) { - 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 (controller->legacy) { - int irq = (unit == 0 ? 14 : 15); + struct ata_pci_controller *controller = device_get_softc(dev); + struct resource *res = NULL; + + if (device_get_devclass(child) == ata_devclass) { + int unit = ((struct ata_channel *)device_get_softc(child))->unit; + int myrid; + + if (type == SYS_RES_IOPORT) { + switch (*rid) { + case ATA_IOADDR_RID: + if (controller->legacy) { + 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 (controller->legacy) { + 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 (controller->legacy) { + int irq = (unit == 0 ? 14 : 15); - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IRQ, rid, irq, irq, 1, flags); + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_IRQ, rid, irq, irq, 1, flags); + } else + res = controller->r_irq; + } + } else { + if (type == SYS_RES_IRQ) { + if (*rid != ATA_IRQ_RID) + return (NULL); + res = controller->r_irq; + } else { + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + type, rid, start, end, count, flags); + } } - else - res = controller->r_irq; - } - return res; + return (res); } int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { - struct ata_pci_controller *controller = device_get_softc(dev); - 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 (controller->legacy) { - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IRQ, rid, r); + if (device_get_devclass(child) == ata_devclass) { + struct ata_pci_controller *controller = device_get_softc(dev); + 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); + case ATA_CTLADDR_RID: + return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IOPORT, + PCIR_BAR(1) + (unit << 3), r); + default: + return ENOENT; + } + } + if (type == SYS_RES_IRQ) { + if (rid != ATA_IRQ_RID) + return ENOENT; + if (controller->legacy) { + return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, + SYS_RES_IRQ, rid, r); + } else + return 0; + } + } else { + if (type == SYS_RES_IRQ) { + if (rid != ATA_IRQ_RID) + return (ENOENT); + return (0); + } else { + return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child, + type, rid, r)); + } } - else - return 0; - } - return EINVAL; + return (EINVAL); } int @@ -281,44 +328,50 @@ ata_pci_setup_intr(device_t dev, device_ int flags, driver_filter_t *filter, driver_intr_t *function, void *argument, void **cookiep) { - struct ata_pci_controller *controller = device_get_softc(dev); + struct ata_pci_controller *controller = device_get_softc(dev); - if (controller->legacy) { - return BUS_SETUP_INTR(device_get_parent(dev), child, irq, + if (controller->legacy) { + 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; + } else { + struct ata_pci_controller *controller = device_get_softc(dev); + int unit; - if (filter != NULL) { - printf("ata-pci.c: we cannot use a filter here\n"); - return (EINVAL); + if (filter != NULL) { + printf("ata-pci.c: we cannot use a filter here\n"); + return (EINVAL); + } + if (device_get_devclass(child) == ata_devclass) + unit = ((struct ata_channel *)device_get_softc(child))->unit; + else + unit = ATA_PCI_MAX_CH - 1; + controller->interrupt[unit].function = function; + controller->interrupt[unit].argument = argument; + *cookiep = controller; + return 0; } - controller->interrupt[unit].function = function; - controller->interrupt[unit].argument = argument; - *cookiep = controller; - return 0; - } } int ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { - struct ata_pci_controller *controller = device_get_softc(dev); - - if (controller->legacy) { - 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; - } + if (controller->legacy) { + return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); + } else { + struct ata_pci_controller *controller = device_get_softc(dev); + int unit; + + if (device_get_devclass(child) == ata_devclass) + unit = ((struct ata_channel *)device_get_softc(child))->unit; + else + unit = ATA_PCI_MAX_CH - 1; + controller->interrupt[unit].function = NULL; + controller->interrupt[unit].argument = NULL; + return 0; + } } static void @@ -510,12 +563,16 @@ static device_method_t ata_pci_methods[] DEVMETHOD(device_shutdown, bus_generic_shutdown), /* bus methods */ + DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), + DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), DEVMETHOD(bus_release_resource, ata_pci_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), + DEVMETHOD(pci_read_config, ata_pci_read_config), + DEVMETHOD(pci_write_config, ata_pci_write_config), { 0, 0 } }; @@ -537,6 +594,8 @@ ata_pcichannel_probe(device_t dev) { char buffer[32]; + if ((intptr_t)device_get_ivars(dev) < 0) + return (ENXIO); sprintf(buffer, "ATA channel %d", (int)(intptr_t)device_get_ivars(dev)); device_set_desc_copy(dev, buffer); @@ -711,7 +770,7 @@ ata_generic_intr(void *data) struct ata_channel *ch; int unit; - for (unit = 0; unit < ctlr->channels; unit++) { + for (unit = 0; unit < ATA_PCI_MAX_CH; unit++) { if ((ch = ctlr->interrupt[unit].argument)) ctlr->interrupt[unit].function(ch); } Modified: head/sys/dev/ata/ata-pci.h ============================================================================== --- head/sys/dev/ata/ata-pci.h Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ata/ata-pci.h Mon Nov 16 15:38:27 2009 (r199322) @@ -36,6 +36,8 @@ struct ata_chip_id { char *text; }; +#define ATA_PCI_MAX_CH 8 + /* structure describing a PCI ATA controller */ struct ata_pci_controller { device_t dev; @@ -65,7 +67,7 @@ struct ata_pci_controller { struct { void (*function)(void *); void *argument; - } interrupt[8]; /* XXX SOS max ch# for now */ + } interrupt[ATA_PCI_MAX_CH]; void *chipset_data; }; @@ -486,6 +488,11 @@ int ata_pci_attach(device_t dev); int ata_pci_detach(device_t dev); int ata_pci_suspend(device_t dev); int ata_pci_resume(device_t dev); +int ata_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); +int ata_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value); +uint32_t ata_pci_read_config(device_t dev, device_t child, int reg, int width); +void ata_pci_write_config(device_t dev, device_t child, int reg, + uint32_t val, int width); 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); int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r); 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); @@ -509,12 +516,6 @@ int ata_mode2idx(int mode); /* global prototypes from chipsets/ata-*.c */ int ata_ahci_chipinit(device_t); -int ata_ahci_ch_attach(device_t dev); -int ata_ahci_ch_detach(device_t dev); -int ata_ahci_ch_suspend(device_t dev); -int ata_ahci_ch_resume(device_t dev); -int ata_ahci_ctlr_reset(device_t dev); -void ata_ahci_reset(device_t dev); int ata_marvell_edma_chipinit(device_t); int ata_sii_chipinit(device_t); @@ -530,12 +531,16 @@ static device_method_t __CONCAT(dname,_m DEVMETHOD(device_suspend, ata_pci_suspend), \ DEVMETHOD(device_resume, ata_pci_resume), \ DEVMETHOD(device_shutdown, bus_generic_shutdown), \ + DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), \ + DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), \ DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), \ DEVMETHOD(bus_release_resource, ata_pci_release_resource), \ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), \ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), \ DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), \ DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), \ + DEVMETHOD(pci_read_config, ata_pci_read_config), \ + DEVMETHOD(pci_write_config, ata_pci_write_config), \ { 0, 0 } \ }; \ static driver_t __CONCAT(dname,_driver) = { \ Modified: head/sys/dev/ata/chipsets/ata-ahci.c ============================================================================== --- head/sys/dev/ata/chipsets/ata-ahci.c Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ata/chipsets/ata-ahci.c Mon Nov 16 15:38:27 2009 (r199322) @@ -52,6 +52,12 @@ __FBSDID("$FreeBSD$"); #include <ata_if.h> /* local prototypes */ +static int ata_ahci_ch_attach(device_t dev); +static int ata_ahci_ch_detach(device_t dev); +static int ata_ahci_ch_suspend(device_t dev); +static int ata_ahci_ch_resume(device_t dev); +static int ata_ahci_ctlr_reset(device_t dev); +static void ata_ahci_reset(device_t dev); static int ata_ahci_suspend(device_t dev); static int ata_ahci_status(device_t dev); static int ata_ahci_begin_transaction(struct ata_request *request); @@ -97,6 +103,49 @@ ata_ahci_probe(device_t dev) return (BUS_PROBE_GENERIC); } +static int +ata_ahci_ata_probe(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if ((intptr_t)device_get_ivars(dev) >= 0) + return (ENXIO); + device_set_desc_copy(dev, "AHCI SATA controller"); + ctlr->chipinit = ata_ahci_chipinit; + return (BUS_PROBE_GENERIC); +} + +static int +ata_ahci_ata_attach(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + device_t child; + int unit; + + /* do chipset specific setups only needed once */ + ctlr->legacy = 0; + ctlr->ichannels = -1; + ctlr->ch_attach = ata_pci_ch_attach; + ctlr->ch_detach = ata_pci_ch_detach; + ctlr->dev = dev; + 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_ahci_chipinit(device_t dev) { @@ -129,9 +178,15 @@ ata_ahci_chipinit(device_t dev) /* get the number of HW channels */ ctlr->ichannels = ATA_INL(ctlr->r_res2, ATA_AHCI_PI); - ctlr->channels = - MAX(flsl(ctlr->ichannels), + ctlr->channels = MAX(flsl(ctlr->ichannels), (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1); + if (pci_get_devid(dev) == ATA_M88SX6111) + ctlr->channels = 1; + else if (pci_get_devid(dev) == ATA_M88SX6121) + ctlr->channels = 2; + else if (pci_get_devid(dev) == ATA_M88SX6141 || + pci_get_devid(dev) == ATA_M88SX6145) + ctlr->channels = 4; ctlr->reset = ata_ahci_reset; ctlr->ch_attach = ata_ahci_ch_attach; @@ -183,7 +238,7 @@ ata_ahci_chipinit(device_t dev) return 0; } -int +static int ata_ahci_ctlr_reset(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); @@ -228,7 +283,7 @@ ata_ahci_suspend(device_t dev) return 0; } -int +static int ata_ahci_ch_attach(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); @@ -259,7 +314,7 @@ ata_ahci_ch_attach(device_t dev) return 0; } -int +static int ata_ahci_ch_detach(device_t dev) { @@ -268,7 +323,7 @@ ata_ahci_ch_detach(device_t dev) return (0); } -int +static int ata_ahci_ch_suspend(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); @@ -293,7 +348,7 @@ ata_ahci_ch_suspend(device_t dev) return (0); } -int +static int ata_ahci_ch_resume(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); @@ -813,7 +868,7 @@ ata_ahci_softreset(device_t dev, int por return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset); } -void +static void ata_ahci_reset(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); @@ -927,3 +982,26 @@ ata_ahci_setup_fis(struct ata_ahci_cmd_t } ATA_DECLARE_DRIVER(ata_ahci); +static device_method_t ata_ahci_ata_methods[] = { + DEVMETHOD(device_probe, ata_ahci_ata_probe), + DEVMETHOD(device_attach, ata_ahci_ata_attach), + DEVMETHOD(device_detach, ata_pci_detach), + DEVMETHOD(device_suspend, ata_pci_suspend), + DEVMETHOD(device_resume, ata_pci_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(bus_read_ivar, ata_pci_read_ivar), + DEVMETHOD(bus_write_ivar, ata_pci_write_ivar), + DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), + DEVMETHOD(bus_release_resource, ata_pci_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), + DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), + { 0, 0 } +}; +static driver_t ata_ahci_ata_driver = { + "atapci", + ata_ahci_ata_methods, + sizeof(struct ata_pci_controller) +}; +DRIVER_MODULE(ata_ahci_ata, atapci, ata_ahci_ata_driver, ata_pci_devclass, 0, 0); Modified: head/sys/dev/ata/chipsets/ata-jmicron.c ============================================================================== --- head/sys/dev/ata/chipsets/ata-jmicron.c Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ata/chipsets/ata-jmicron.c Mon Nov 16 15:38:27 2009 (r199322) @@ -53,11 +53,6 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_jmicron_chipinit(device_t dev); -static int ata_jmicron_ch_attach(device_t dev); -static int ata_jmicron_ch_detach(device_t dev); -static int ata_jmicron_ch_suspend(device_t dev); -static int ata_jmicron_ch_resume(device_t dev); -static void ata_jmicron_reset(device_t dev); static void ata_jmicron_setmode(device_t dev, int mode); /* @@ -70,10 +65,10 @@ ata_jmicron_probe(device_t dev) struct ata_chip_id *idx; static struct ata_chip_id ids[] = {{ ATA_JMB360, 0, 1, 0, ATA_SA300, "JMB360" }, - { ATA_JMB361, 0, 1, 1, ATA_SA300, "JMB361" }, - { ATA_JMB363, 0, 2, 1, ATA_SA300, "JMB363" }, - { ATA_JMB365, 0, 1, 2, ATA_SA300, "JMB365" }, - { ATA_JMB366, 0, 2, 2, ATA_SA300, "JMB366" }, + { ATA_JMB361, 0, 1, 1, ATA_UDMA6, "JMB361" }, + { ATA_JMB363, 0, 2, 1, ATA_UDMA6, "JMB363" }, + { ATA_JMB365, 0, 1, 2, ATA_UDMA6, "JMB365" }, + { ATA_JMB366, 0, 2, 2, ATA_UDMA6, "JMB366" }, { ATA_JMB368, 0, 0, 1, ATA_UDMA6, "JMB368" }, { 0, 0, 0, 0, 0, 0}}; char buffer[64]; @@ -101,7 +96,7 @@ static int ata_jmicron_chipinit(device_t dev) { struct ata_pci_controller *ctlr = device_get_softc(dev); - int error; + device_t child; if (ata_setup_interrupt(dev, ata_generic_intr)) return ENXIO; @@ -123,116 +118,35 @@ ata_jmicron_chipinit(device_t dev) /* set controller configuration to a combined setup we support */ pci_write_config(dev, 0x40, 0x80c0a131, 4); pci_write_config(dev, 0x80, 0x01200000, 4); - - if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev))) - return error; - - ctlr->ch_attach = ata_jmicron_ch_attach; - ctlr->ch_detach = ata_jmicron_ch_detach; - ctlr->ch_suspend = ata_jmicron_ch_suspend; - ctlr->ch_resume = ata_jmicron_ch_resume; - ctlr->reset = ata_jmicron_reset; + /* Create AHCI subdevice if AHCI part present. */ + if (ctlr->chip->cfg1) { + child = device_add_child(dev, NULL, -1); + if (child != NULL) { + device_set_ivars(child, (void *)(intptr_t)-1); + bus_generic_attach(dev); + } + } + ctlr->ch_attach = ata_pci_ch_attach; + ctlr->ch_detach = ata_pci_ch_detach; + ctlr->reset = ata_generic_reset; ctlr->setmode = ata_jmicron_setmode; - - /* set the number of HW channels */ - ctlr->channels = ctlr->chip->cfg1 + ctlr->chip->cfg2; - ctlr->ichannels |= ((0xffffffffU >> (32 - ctlr->chip->cfg2)) - << ctlr->chip->cfg1); + ctlr->channels = ctlr->chip->cfg2; } return 0; } -static int -ata_jmicron_ch_attach(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int error; - - if (ch->unit >= ctlr->chip->cfg1) { - ch->unit -= ctlr->chip->cfg1; - error = ata_pci_ch_attach(dev); - ch->unit += ctlr->chip->cfg1; - } - else - error = ata_ahci_ch_attach(dev); - return error; -} - -static int -ata_jmicron_ch_detach(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int error; - - if (ch->unit >= ctlr->chip->cfg1) { - ch->unit -= ctlr->chip->cfg1; - error = ata_pci_ch_detach(dev); - ch->unit += ctlr->chip->cfg1; - } - else - error = ata_ahci_ch_detach(dev); - - return (error); -} - -static int -ata_jmicron_ch_suspend(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int error = 0; - - if (ch->unit < ctlr->chip->cfg1) - error = ata_ahci_ch_suspend(dev); - return error; -} - -static int -ata_jmicron_ch_resume(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - int error = 0; - - if (ch->unit < ctlr->chip->cfg1) - error = ata_ahci_ch_resume(dev); - return (error); -} - -static void -ata_jmicron_reset(device_t dev) -{ - struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); - struct ata_channel *ch = device_get_softc(dev); - - if (ch->unit >= ctlr->chip->cfg1) - ata_generic_reset(dev); - else - ata_ahci_reset(dev); -} - static void ata_jmicron_setmode(device_t dev, int mode) { - struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); - struct ata_channel *ch = device_get_softc(device_get_parent(dev)); - - if (pci_read_config(dev, 0xdf, 1) & 0x40 || ch->unit >= ctlr->chip->cfg1) { struct ata_device *atadev = device_get_softc(dev); /* check for 80pin cable present */ if (pci_read_config(dev, 0x40, 1) & 0x08) - mode = ata_limit_mode(dev, mode, ATA_UDMA2); + mode = ata_limit_mode(dev, mode, ATA_UDMA2); else - mode = ata_limit_mode(dev, mode, ATA_UDMA6); - + mode = ata_limit_mode(dev, mode, ATA_UDMA6); if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode)) - atadev->mode = mode; - } - else - ata_sata_setmode(dev, mode); + atadev->mode = mode; } ATA_DECLARE_DRIVER(ata_jmicron); Modified: head/sys/dev/ata/chipsets/ata-marvell.c ============================================================================== --- head/sys/dev/ata/chipsets/ata-marvell.c Mon Nov 16 15:18:02 2009 (r199321) +++ head/sys/dev/ata/chipsets/ata-marvell.c Mon Nov 16 15:38:27 2009 (r199322) @@ -54,9 +54,7 @@ __FBSDID("$FreeBSD$"); /* local prototypes */ static int ata_marvell_chipinit(device_t dev); static int ata_marvell_ch_attach(device_t dev); -static int ata_marvell_ch_detach(device_t dev); static void ata_marvell_setmode(device_t dev, int mode); -static void ata_marvell_reset(device_t dev); static int ata_marvell_edma_ch_attach(device_t dev); static int ata_marvell_edma_ch_detach(device_t dev); static int ata_marvell_edma_status(device_t dev); @@ -111,10 +109,10 @@ ata_marvell_probe(device_t dev) { ATA_M88SX7042, 0, 4, MV_7042, ATA_SA300, "88SX7042" }, { ATA_M88SX6101, 0, 0, MV_61XX, ATA_UDMA6, "88SX6101" }, { ATA_M88SX6102, 0, 0, MV_61XX, ATA_UDMA6, "88SX6102" }, - { ATA_M88SX6111, 0, 1, MV_61XX, ATA_SA300, "88SX6111" }, - { ATA_M88SX6121, 0, 2, MV_61XX, ATA_SA300, "88SX6121" }, - { ATA_M88SX6141, 0, 4, MV_61XX, ATA_SA300, "88SX6141" }, - { ATA_M88SX6145, 0, 4, MV_61XX, ATA_SA300, "88SX6145" }, + { ATA_M88SX6111, 0, 1, MV_61XX, ATA_UDMA6, "88SX6111" }, + { ATA_M88SX6121, 0, 2, MV_61XX, ATA_UDMA6, "88SX6121" }, + { ATA_M88SX6141, 0, 4, MV_61XX, ATA_UDMA6, "88SX6141" }, + { ATA_M88SX6145, 0, 4, MV_61XX, ATA_UDMA6, "88SX6145" }, { 0, 0, 0, 0, 0, 0}}; if (pci_get_vendor(dev) != ATA_MARVELL_ID) @@ -142,83 +140,50 @@ ata_marvell_probe(device_t dev) static int ata_marvell_chipinit(device_t dev) { - struct ata_pci_controller *ctlr = device_get_softc(dev); - int error = 0; - - if (ata_setup_interrupt(dev, ata_generic_intr)) - return ENXIO; + struct ata_pci_controller *ctlr = device_get_softc(dev); + device_t child; - if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev))) - return (error); - ctlr->ch_attach = ata_marvell_ch_attach; - ctlr->ch_detach = ata_marvell_ch_detach; - ctlr->reset = ata_marvell_reset; - ctlr->setmode = ata_marvell_setmode; - ctlr->channels = ctlr->chip->cfg1 + 1; - return (0); + if (ata_setup_interrupt(dev, ata_generic_intr)) + return ENXIO; + /* Create AHCI subdevice if AHCI part present. */ + if (ctlr->chip->cfg1) { + child = device_add_child(dev, NULL, -1); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911161538.nAGFcRsS074268>