diff options
Diffstat (limited to 'sys/dev/ata/ata-all.c')
-rw-r--r-- | sys/dev/ata/ata-all.c | 130 |
1 files changed, 73 insertions, 57 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index e275b6a..2f1f317 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,7 +62,6 @@ static struct cdevsw ata_cdevsw = { /* prototypes */ static void ata_boot_attach(void); static device_t ata_add_child(device_t, struct ata_device *, int); -static int ata_getparam(struct ata_device *, int); static void bswap(int8_t *, int); static void btrim(int8_t *, int); static void bpack(int8_t *, int8_t *, int); @@ -75,6 +74,7 @@ devclass_t ata_devclass; uma_zone_t ata_request_zone; uma_zone_t ata_composite_zone; int ata_wc = 1; +int ata_setmax = 0; /* local vars */ static int ata_dma = 1; @@ -91,6 +91,9 @@ SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RDTUN, &atapi_dma, 0, TUNABLE_INT("hw.ata.wc", &ata_wc); SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RDTUN, &ata_wc, 0, "ATA disk write caching"); +TUNABLE_INT("hw.ata.setmax", &ata_setmax); +SYSCTL_INT(_hw_ata, OID_AUTO, setmax, CTLFLAG_RDTUN, &ata_setmax, 0, + "ATA disk set max native address"); /* * newbus device interface related functions @@ -404,13 +407,13 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data, if (children[i] && device_is_attached(children[i])) { struct ata_device *atadev = device_get_softc(children[i]); - if (atadev->unit == ATA_MASTER) { + if (atadev->unit == ATA_MASTER) { /* XXX SOS PM */ strncpy(devices->name[0], device_get_nameunit(children[i]), 32); bcopy(&atadev->param, &devices->params[0], sizeof(struct ata_params)); } - if (atadev->unit == ATA_SLAVE) { + if (atadev->unit == ATA_SLAVE) { /* XXX SOS PM */ strncpy(devices->name[1], device_get_nameunit(children[i]), 32); bcopy(&atadev->param, &devices->params[1], @@ -569,7 +572,7 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit) return child; } -static int +int ata_getparam(struct ata_device *atadev, int init) { struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev)); @@ -577,11 +580,9 @@ ata_getparam(struct ata_device *atadev, int init) u_int8_t command = 0; int error = ENOMEM, retries = 2; - if (ch->devices & - (atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE)) + if (ch->devices & (ATA_ATA_MASTER << atadev->unit)) command = ATA_ATA_IDENTIFY; - if (ch->devices & - (atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE)) + if (ch->devices & (ATA_ATAPI_MASTER << atadev->unit)) command = ATA_ATAPI_IDENTIFY; if (!command) return ENXIO; @@ -631,7 +632,7 @@ ata_getparam(struct ata_device *atadev, int init) if (bootverbose) printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n", device_get_unit(ch->dev), - atadev->unit == ATA_MASTER ? "master" : "slave", + ata_unit2str(atadev), ata_mode2str(ata_pmode(atacap)), ata_mode2str(ata_wmode(atacap)), ata_mode2str(ata_umode(atacap)), @@ -643,13 +644,13 @@ ata_getparam(struct ata_device *atadev, int init) if ((atadev->param.config & ATA_PROTO_ATAPI) && (atadev->param.config != ATA_CFA_MAGIC1) && (atadev->param.config != ATA_CFA_MAGIC2)) { - if (atapi_dma && ch->dma && + if (atapi_dma && (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR && ata_umode(&atadev->param) >= ATA_UDMA2) atadev->mode = ATA_DMA_MAX; } else { - if (ata_dma && ch->dma && + if (ata_dma && (ata_umode(&atadev->param) > 0 || ata_wmode(&atadev->param) > 0)) atadev->mode = ATA_DMA_MAX; @@ -667,52 +668,39 @@ int ata_identify(device_t dev) { struct ata_channel *ch = device_get_softc(dev); - struct ata_device *master = NULL, *slave = NULL; - device_t master_child = NULL, slave_child = NULL; - int master_unit = -1, slave_unit = -1; - - if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) { - if (!(master = malloc(sizeof(struct ata_device), - M_ATA, M_NOWAIT | M_ZERO))) { - device_printf(dev, "out of memory\n"); - return ENOMEM; - } - master->unit = ATA_MASTER; - } - if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) { - if (!(slave = malloc(sizeof(struct ata_device), - M_ATA, M_NOWAIT | M_ZERO))) { - free(master, M_ATA); - device_printf(dev, "out of memory\n"); - return ENOMEM; - } - slave->unit = ATA_SLAVE; - } + struct ata_device *devices[ATA_PM]; + device_t childdevs[ATA_PM]; + int i, unit = -1; + if (bootverbose) + device_printf(dev, "identify ch->devices=%08x\n", ch->devices); + + for (i = 0; i < ATA_PM; ++i) { + if (ch->devices & (((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << i))) { + if (!(devices[i] = malloc(sizeof(struct ata_device), + M_ATA, M_NOWAIT | M_ZERO))) { + device_printf(dev, "out of memory\n"); + return ENOMEM; + } + devices[i]->unit = i; #ifdef ATA_STATIC_ID - if (ch->devices & ATA_ATA_MASTER) - master_unit = (device_get_unit(dev) << 1); -#endif - if (master && !(master_child = ata_add_child(dev, master, master_unit))) { - free(master, M_ATA); - master = NULL; - } -#ifdef ATA_STATIC_ID - if (ch->devices & ATA_ATA_SLAVE) - slave_unit = (device_get_unit(dev) << 1) + 1; + unit = (device_get_unit(dev) << 1) + i; #endif - if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) { - free(slave, M_ATA); - slave = NULL; - } - - if (slave && ata_getparam(slave, 1)) { - device_delete_child(dev, slave_child); - free(slave, M_ATA); - } - if (master && ata_getparam(master, 1)) { - device_delete_child(dev, master_child); - free(master, M_ATA); + if (!(childdevs[i] = ata_add_child(dev, devices[i], unit))) { + free(devices[i], M_ATA); + devices[i]=NULL; + } + else { + if (ata_getparam(devices[i], 1)) { + device_delete_child(dev, childdevs[i]); + free(devices[i], M_ATA); + childdevs[i] = NULL; + devices[i] = NULL; + } + } + } + devices[i] = NULL; + childdevs[i] = NULL; } bus_generic_probe(dev); @@ -810,8 +798,23 @@ ata_modify_if_48bit(struct ata_request *request) case ATA_FLUSHCACHE: request->u.ata.command = ATA_FLUSHCACHE48; break; - case ATA_READ_NATIVE_MAX_ADDDRESS: - request->u.ata.command = ATA_READ_NATIVE_MAX_ADDDRESS48; + case ATA_SET_MAX_ADDRESS: + request->u.ata.command = ATA_SET_MAX_ADDRESS48; + break; + default: + return; + } + atadev->flags |= ATA_D_48BIT_ACTIVE; + } + else if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) { + + /* translate command into 48bit version */ + switch (request->u.ata.command) { + case ATA_FLUSHCACHE: + request->u.ata.command = ATA_FLUSHCACHE48; + break; + case ATA_READ_NATIVE_MAX_ADDRESS: + request->u.ata.command = ATA_READ_NATIVE_MAX_ADDRESS48; break; case ATA_SET_MAX_ADDRESS: request->u.ata.command = ATA_SET_MAX_ADDRESS48; @@ -834,6 +837,19 @@ ata_udelay(int interval) } char * +ata_unit2str(struct ata_device *atadev) +{ + struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev)); + static char str[8]; + + if (ch->devices & ATA_PORTMULTIPLIER) + sprintf(str, "port%d", atadev->unit); + else + sprintf(str, "%s", atadev->unit == ATA_MASTER ? "master" : "slave"); + return str; +} + +char * ata_mode2str(int mode) { switch (mode) { |