Ejemplo n.º 1
0
static void 
ast_describe(struct ast_softc *stp)
{
    if (bootverbose) {
	ata_prtdev(stp->device, "<%.40s/%.8s> tape drive at ata%d as %s\n",
		   stp->device->param->model, stp->device->param->revision,
		   device_get_unit(stp->device->channel->dev),
		   (stp->device->unit == ATA_MASTER) ? "master" : "slave");
	ata_prtdev(stp->device, "%dKB/s, ", stp->cap.max_speed);
	printf("transfer limit %d blk%s, ",
	       stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : "");
	printf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024);
	printf("%s\n", ata_mode2str(stp->device->mode));
	ata_prtdev(stp->device, "Medium: ");
	switch (stp->cap.medium_type) {
	    case 0x00:
		printf("none"); break;
	    case 0x17:
		printf("Travan 1 (400 Mbyte)"); break;
	    case 0xb6:
		printf("Travan 4 (4 Gbyte)"); break;
	    case 0xda:
		printf("OnStream ADR (15Gyte)"); break;
	    default:
		printf("unknown (0x%x)", stp->cap.medium_type);
	}
	if (stp->cap.readonly) printf(", readonly");
	if (stp->cap.reverse) printf(", reverse");
	if (stp->cap.eformat) printf(", eformat");
	if (stp->cap.qfa) printf(", qfa");
	if (stp->cap.lock) printf(", lock");
	if (stp->cap.locked) printf(", locked");
	if (stp->cap.prevent) printf(", prevent");
	if (stp->cap.eject) printf(", eject");
	if (stp->cap.disconnect) printf(", disconnect");
	if (stp->cap.ecc) printf(", ecc");
	if (stp->cap.compress) printf(", compress");
	if (stp->cap.blk512) printf(", 512b");
	if (stp->cap.blk1024) printf(", 1024b");
	if (stp->cap.blk32k) printf(", 32kb");
	printf("\n");
    }
    else {
	ata_prtdev(stp->device, "TAPE <%.40s> at ata%d-%s %s\n",
		   stp->device->param->model,
		   device_get_unit(stp->device->channel->dev),
		   (stp->device->unit == ATA_MASTER) ? "master" : "slave",
		   ata_mode2str(stp->device->mode));
    }
}
Ejemplo n.º 2
0
/*
 * JMicron chipset support functions
 */
static int
ata_jmicron_probe(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    const struct ata_chip_id *idx;
    static const struct ata_chip_id ids[] =
    {{ ATA_JMB360, 0, 1, 0, ATA_SA300, "JMB360" },
     { ATA_JMB361, 0, 1, 1, ATA_UDMA6, "JMB361" },
     { ATA_JMB362, 0, 2, 0, ATA_SA300, "JMB362" },
     { 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" },
     { ATA_JMB368_2, 0, 0, 1, ATA_UDMA6, "JMB368" },
     { 0, 0, 0, 0, 0, 0}};
    char buffer[64];

    if (pci_get_vendor(dev) != ATA_JMICRON_ID)
	return ENXIO;

    if (!(idx = ata_match_chip(dev, ids)))
        return ENXIO;

    sprintf(buffer, "JMicron %s %s controller",
	idx->text, ata_mode2str(idx->max_dma));
    device_set_desc_copy(dev, buffer);
    ctlr->chip = idx;
    ctlr->chipinit = ata_jmicron_chipinit;
    return (BUS_PROBE_LOW_PRIORITY);
}
Ejemplo n.º 3
0
static void 
afd_describe(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_device *atadev = device_get_softc(dev);
    struct afd_softc *fdp = device_get_ivars(dev);
    char sizestring[16];

    if (fdp->mediasize > 1048576 * 5)
	ksprintf(sizestring, "%lluMB", (unsigned long long)
		(fdp->mediasize / 1048576));
    else if (fdp->mediasize)
	ksprintf(sizestring, "%lluKB", (unsigned long long)
		(fdp->mediasize / 1024));
    else
	strcpy(sizestring, "(no media)");
 
    device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s\n",
		  sizestring, atadev->param.model, atadev->param.revision,
		  device_get_unit(ch->dev),
		  (atadev->unit == ATA_MASTER) ? "master" : "slave",
		  ata_mode2str(atadev->mode));
    if (bootverbose) {
	device_printf(dev, "%llu sectors [%lluC/%dH/%dS]\n",
	    	      (unsigned long long)(fdp->mediasize / fdp->sectorsize),
	    	      (unsigned long long)
		     (fdp->mediasize/(fdp->sectorsize*fdp->sectors*fdp->heads)),
	    	      fdp->heads, fdp->sectors);
    }
}
Ejemplo n.º 4
0
static void 
afd_describe(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_device *atadev = device_get_softc(dev);
    struct afd_softc *fdp = device_get_ivars(dev);
    char sizestring[16];

    if (fdp->mediasize > 1048576 * 5)
	sprintf(sizestring, "%juMB", fdp->mediasize / 1048576);
    else if (fdp->mediasize)
	sprintf(sizestring, "%juKB", fdp->mediasize / 1024);
    else
	strcpy(sizestring, "(no media)");
 
    device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s %s\n",
		  sizestring, atadev->param.model, atadev->param.revision,
		  device_get_unit(ch->dev), ata_unit2str(atadev),
		  ata_mode2str(atadev->mode),
		  ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
    if (bootverbose) {
	device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n",
	    	      fdp->mediasize / fdp->sectorsize,
	    	      fdp->mediasize /(fdp->sectorsize*fdp->sectors*fdp->heads),
	    	      fdp->heads, fdp->sectors);
    }
}
Ejemplo n.º 5
0
void
ata_set_desc(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    char buffer[128];

    sprintf(buffer, "%s %s %s controller",
            ata_pcivendor2str(dev), ctlr->chip->text, 
            ata_mode2str(ctlr->chip->max_dma));
    device_set_desc_copy(dev, buffer);
}
Ejemplo n.º 6
0
static void
ata_devel_setmode(device_t dev, int mode)
{
    struct ata_device *atadev = device_get_softc(dev);
    int error;

    error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
			   ata_limit_mode(dev, mode, ATA_UDMA5));
    if (bootverbose)
	device_printf(dev, "%ssetting %s on DEVEL chip\n",
		      (error) ? "FAILURE " : "", ata_mode2str(mode));
    if (!error)
	atadev->mode = mode;
}
Ejemplo n.º 7
0
void
ad_describe(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_device *atadev = device_get_softc(dev);
    struct ad_softc *adp = device_get_ivars(dev);
    u_int8_t *marker, vendor[64], product[64];

    /* try to seperate the ATA model string into vendor and model parts */
    if ((marker = index(atadev->param.model, ' ')) ||
	(marker = index(atadev->param.model, '-'))) {
	int len = (marker - atadev->param.model);

	strncpy(vendor, atadev->param.model, len);
	vendor[len++] = 0;
	strcat(vendor, " ");
	strncpy(product, atadev->param.model + len, 40 - len);
	vendor[40 - len] = 0;
    }
    else {
	if (!strncmp(atadev->param.model, "ST", 2))
	    strcpy(vendor, "Seagate ");
	else if (!strncmp(atadev->param.model, "HDS", 3))
	    strcpy(vendor, "Hitachi ");
	else
	    strcpy(vendor, "");
	strncpy(product, atadev->param.model, 40);
    }

    device_printf(dev, "%lluMB <%s%s %.8s> at ata%d-%s %s%s\n",
		  (unsigned long long)(adp->total_secs / (1048576 / DEV_BSIZE)),
		  vendor, product, atadev->param.revision,
		  device_get_unit(ch->dev),
		  (atadev->unit == ATA_MASTER) ? "master" : "slave",
		  (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
		  ata_mode2str(atadev->mode));
    if (bootverbose) {
	device_printf(dev, "%llu sectors [%lluC/%dH/%dS] "
		      "%d sectors/interrupt %d depth queue\n",
		      (unsigned long long)adp->total_secs,(unsigned long long)(
		      adp->total_secs / (adp->heads * adp->sectors)),
		      adp->heads, adp->sectors, atadev->max_iosize / DEV_BSIZE,
		      adp->num_tags + 1);
    }
}
Ejemplo n.º 8
0
static void
ata_amd_setmode(device_t dev, int mode)
{
    device_t gparent = GRANDPARENT(dev);
    struct ata_pci_controller *ctlr = device_get_softc(gparent);
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_device *atadev = device_get_softc(dev);
    u_int8_t timings[] = { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20,
			   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
    int modes[7] = { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 };
    int devno = (ch->unit << 1) + atadev->unit;
    int reg = 0x53 - devno;
    int error;

    mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);

    if (ctlr->chip->cfg1 & AMD_CABLE) {
	if (mode > ATA_UDMA2 &&
	    !(pci_read_config(gparent, 0x42, 1) & (1 << devno))) {
	    ata_print_cable(dev, "controller");
	    mode = ATA_UDMA2;
	}
    }
    else 
	mode = ata_check_80pin(dev, mode);


    error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
    if (bootverbose)
	device_printf(dev, "%ssetting %s on %s chip\n",
		      (error) ? "FAILURE " : "", ata_mode2str(mode),
		      ctlr->chip->text);
    if (!error) {
	pci_write_config(gparent, reg - 0x08, timings[ata_mode2idx(mode)], 1);
	if (mode >= ATA_UDMA0)
	    pci_write_config(gparent, reg, modes[mode & ATA_MODE_MASK], 1);
	else
	    pci_write_config(gparent, reg, 0x8b, 1);
	atadev->mode = mode;
    }
}
Ejemplo n.º 9
0
/*
 * HighPoint chipset support functions
 */
static int
ata_highpoint_probe(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    const struct ata_chip_id *idx;
    static const struct ata_chip_id ids[] =
    {{ ATA_HPT374, 0x07, HPT_374, 0,       ATA_UDMA6, "HPT374" },
     { ATA_HPT372, 0x02, HPT_372, 0,       ATA_UDMA6, "HPT372N" },
     { ATA_HPT372, 0x01, HPT_372, 0,       ATA_UDMA6, "HPT372" },
     { ATA_HPT371, 0x01, HPT_372, 0,       ATA_UDMA6, "HPT371" },
     { ATA_HPT366, 0x05, HPT_372, 0,       ATA_UDMA6, "HPT372" },
     { ATA_HPT366, 0x03, HPT_370, 0,       ATA_UDMA5, "HPT370" },
     { ATA_HPT366, 0x02, HPT_366, 0,       ATA_UDMA4, "HPT368" },
     { ATA_HPT366, 0x00, HPT_366, HPT_OLD, ATA_UDMA4, "HPT366" },
     { ATA_HPT302, 0x01, HPT_372, 0,       ATA_UDMA6, "HPT302" },
     { 0, 0, 0, 0, 0, 0}};
    char buffer[64];

    if (pci_get_vendor(dev) != ATA_HIGHPOINT_ID)
        return ENXIO;

    if (!(idx = ata_match_chip(dev, ids)))
	return ENXIO;

    strcpy(buffer, "HighPoint ");
    strcat(buffer, idx->text);
    if (idx->cfg1 == HPT_374) {
	if (pci_get_function(dev) == 0)
	    strcat(buffer, " (channel 0+1)");
	if (pci_get_function(dev) == 1)
	    strcat(buffer, " (channel 2+3)");
    }
    sprintf(buffer, "%s %s controller", buffer, ata_mode2str(idx->max_dma));
    device_set_desc_copy(dev, buffer);
    ctlr->chip = idx;
    ctlr->chipinit = ata_highpoint_chipinit;
    return (BUS_PROBE_LOW_PRIORITY);
}
Ejemplo n.º 10
0
static int
ata_getparam(struct ata_device *atadev, int init)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(atadev->dev));
    struct ata_request *request;
    u_int8_t command = 0;
    int error = ENOMEM, retries = 2;

    if (ch->devices &
	(atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
	command = ATA_ATA_IDENTIFY;
    if (ch->devices &
	(atadev->unit == ATA_MASTER ? ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))
	command = ATA_ATAPI_IDENTIFY;
    if (!command)
	return ENXIO;

    while (retries-- > 0 && error) {
	if (!(request = ata_alloc_request()))
	    break;
	request->dev = atadev->dev;
	request->timeout = 1;
	request->retries = 0;
	request->u.ata.command = command;
	request->flags = (ATA_R_READ|ATA_R_AT_HEAD|ATA_R_DIRECT|ATA_R_QUIET);
	request->data = (void *)&atadev->param;
	request->bytecount = sizeof(struct ata_params);
	request->donecount = 0;
	request->transfersize = DEV_BSIZE;
	ata_queue_request(request);
	error = request->result;
	ata_free_request(request);
    }

    if (!error && (isprint(atadev->param.model[0]) ||
		   isprint(atadev->param.model[1]))) {
	struct ata_params *atacap = &atadev->param;
	char buffer[64];
	int16_t *ptr;

	for (ptr = (int16_t *)atacap;
	     ptr < (int16_t *)atacap + sizeof(struct ata_params)/2; ptr++) {
	    *ptr = le16toh(*ptr);
	}
	if (!(!strncmp(atacap->model, "FX", 2) ||
	      !strncmp(atacap->model, "NEC", 3) ||
	      !strncmp(atacap->model, "Pioneer", 7) ||
	      !strncmp(atacap->model, "SHARP", 5))) {
	    bswap(atacap->model, sizeof(atacap->model));
	    bswap(atacap->revision, sizeof(atacap->revision));
	    bswap(atacap->serial, sizeof(atacap->serial));
	}
	btrim(atacap->model, sizeof(atacap->model));
	bpack(atacap->model, atacap->model, sizeof(atacap->model));
	btrim(atacap->revision, sizeof(atacap->revision));
	bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
	btrim(atacap->serial, sizeof(atacap->serial));
	bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));

	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_mode2str(ata_pmode(atacap)),
		   ata_mode2str(ata_wmode(atacap)),
		   ata_mode2str(ata_umode(atacap)),
		   (atacap->hwres & ATA_CABLE_ID) ? "80":"40");

	if (init) {
	    sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
	    device_set_desc_copy(atadev->dev, buffer);
	    if ((atadev->param.config & ATA_PROTO_ATAPI) &&
		(atadev->param.config != ATA_CFA_MAGIC1) &&
		(atadev->param.config != ATA_CFA_MAGIC2)) {
		if (atapi_dma && ch->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 &&
		    (ata_umode(&atadev->param) > 0 ||
		     ata_wmode(&atadev->param) > 0))
		    atadev->mode = ATA_DMA_MAX;
	    }
	}
    }
    else {
	if (!error)
	    error = ENXIO;
    }
    return error;
}
Ejemplo n.º 11
0
/*
 * Silicon Integrated Systems Corp. (SiS) chipset support functions
 */
static int
ata_sis_probe(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(dev);
    const struct ata_chip_id *idx;
    static const struct ata_chip_id ids[] =
    {   { ATA_SIS182,  0x00, SIS_SATA,   0, ATA_SA150, "182" }, /* south */
        { ATA_SIS181,  0x00, SIS_SATA,   0, ATA_SA150, "181" }, /* south */
        { ATA_SIS180,  0x00, SIS_SATA,   0, ATA_SA150, "180" }, /* south */
        { ATA_SIS965,  0x00, SIS_133NEW, 0, ATA_UDMA6, "965" }, /* south */
        { ATA_SIS964,  0x00, SIS_133NEW, 0, ATA_UDMA6, "964" }, /* south */
        { ATA_SIS963,  0x00, SIS_133NEW, 0, ATA_UDMA6, "963" }, /* south */
        { ATA_SIS962,  0x00, SIS_133NEW, 0, ATA_UDMA6, "962" }, /* south */

        { ATA_SIS745,  0x00, SIS_100NEW, 0, ATA_UDMA5, "745" }, /* 1chip */
        { ATA_SIS735,  0x00, SIS_100NEW, 0, ATA_UDMA5, "735" }, /* 1chip */
        { ATA_SIS733,  0x00, SIS_100NEW, 0, ATA_UDMA5, "733" }, /* 1chip */
        { ATA_SIS730,  0x00, SIS_100OLD, 0, ATA_UDMA5, "730" }, /* 1chip */

        { ATA_SIS635,  0x00, SIS_100NEW, 0, ATA_UDMA5, "635" }, /* 1chip */
        { ATA_SIS633,  0x00, SIS_100NEW, 0, ATA_UDMA5, "633" }, /* unknown */
        { ATA_SIS630,  0x30, SIS_100OLD, 0, ATA_UDMA5, "630S"}, /* 1chip */
        { ATA_SIS630,  0x00, SIS_66,     0, ATA_UDMA4, "630" }, /* 1chip */
        { ATA_SIS620,  0x00, SIS_66,     0, ATA_UDMA4, "620" }, /* 1chip */

        { ATA_SIS550,  0x00, SIS_66,     0, ATA_UDMA5, "550" },
        { ATA_SIS540,  0x00, SIS_66,     0, ATA_UDMA4, "540" },
        { ATA_SIS530,  0x00, SIS_66,     0, ATA_UDMA4, "530" },

        { ATA_SIS5513, 0xc2, SIS_33,     1, ATA_UDMA2, "5513" },
        { ATA_SIS5513, 0x00, SIS_33,     1, ATA_WDMA2, "5513" },
        { 0, 0, 0, 0, 0, 0 }
    };
    static struct ata_chip_id id[] =
    {{ ATA_SISSOUTH, 0x10, 0, 0, 0, "" }, { 0, 0, 0, 0, 0, 0 }};
    char buffer[64];
    int found = 0;

    if (pci_get_class(dev) != PCIC_STORAGE)
        return (ENXIO);

    if (pci_get_vendor(dev) != ATA_SIS_ID)
        return ENXIO;

    if (!(idx = ata_find_chip(dev, ids, -pci_get_slot(dev))))
        return ENXIO;

    if (idx->cfg2) {
        u_int8_t reg57 = pci_read_config(dev, 0x57, 1);

        pci_write_config(dev, 0x57, (reg57 & 0x7f), 1);
        if (pci_read_config(dev, PCIR_DEVVENDOR, 4) == ATA_SIS5518) {
            found = 1;
            memcpy(&id[0], idx, sizeof(id[0]));
            id[0].cfg1 = SIS_133NEW;
            id[0].max_dma = ATA_UDMA6;
            sprintf(buffer, "SiS 962/963 %s controller",
                    ata_mode2str(idx->max_dma));
        }
        pci_write_config(dev, 0x57, reg57, 1);
    }
    if (idx->cfg2 && !found) {
        u_int8_t reg4a = pci_read_config(dev, 0x4a, 1);

        pci_write_config(dev, 0x4a, (reg4a | 0x10), 1);
        if (pci_read_config(dev, PCIR_DEVVENDOR, 4) == ATA_SIS5517) {
            found = 1;
            if (ata_find_chip(dev, id, pci_get_slot(dev))) {
                id[0].cfg1 = SIS_133OLD;
                id[0].max_dma = ATA_UDMA6;
            } else {
                id[0].cfg1 = SIS_100NEW;
                id[0].max_dma = ATA_UDMA5;
            }
            sprintf(buffer, "SiS 961 %s controller",ata_mode2str(idx->max_dma));
        }
        pci_write_config(dev, 0x4a, reg4a, 1);
    }
    if (!found)
        sprintf(buffer,"SiS %s %s controller",
                idx->text, ata_mode2str(idx->max_dma));
    else
        idx = &id[0];

    device_set_desc_copy(dev, buffer);
    ctlr->chip = idx;
    ctlr->chipinit = ata_sis_chipinit;
    return (BUS_PROBE_DEFAULT);
}
Ejemplo n.º 12
0
static void
ata_ati_setmode(device_t dev, int mode)
{
	device_t gparent = GRANDPARENT(dev);
	struct ata_pci_controller *ctlr = device_get_softc(gparent);
	struct ata_channel *ch = device_get_softc(device_get_parent(dev));
	struct ata_device *atadev = device_get_softc(dev);
	int devno = (ch->unit << 1) + atadev->unit;
	int offset = (devno ^ 0x01) << 3;
	int error;
	int piomode;
	static const uint8_t piotimings[] =
			    { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
			      0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
	static const uint8_t dmatimings[] = { 0x77, 0x21, 0x20 };

    mode = ata_limit_mode(dev, mode, ctlr->chip->max_dma);

    mode = ata_check_80pin(dev, mode);

    error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);

    if (bootverbose)
	device_printf(dev, "%ssetting %s on %s chip\n",
		      (error) ? "FAILURE " : "",
		      ata_mode2str(mode), ctlr->chip->text);
    if (!error) {
	if (mode >= ATA_UDMA0) {
	    /* Set UDMA mode, enable UDMA, set WDMA2/PIO4 */
	    pci_write_config(gparent, 0x56,
			     (pci_read_config(gparent, 0x56, 2) &
			      ~(0xf << (devno << 2))) |
			     ((mode & ATA_MODE_MASK) << (devno << 2)), 2);
	    pci_write_config(gparent, 0x54,
			     pci_read_config(gparent, 0x54, 1) |
			     (0x01 << devno), 1);
	    pci_write_config(gparent, 0x44,
			     (pci_read_config(gparent, 0x44, 4) &
			      ~(0xff << offset)) |
			     (dmatimings[2] << offset), 4);
	    piomode = ATA_PIO4;
	} else if (mode >= ATA_WDMA0) {
	    /* Disable UDMA, set WDMA mode and timings, calculate PIO. */
	    pci_write_config(gparent, 0x54,
			     pci_read_config(gparent, 0x54, 1) &
			      ~(0x01 << devno), 1);
	    pci_write_config(gparent, 0x44,
			     (pci_read_config(gparent, 0x44, 4) &
			      ~(0xff << offset)) |
			     (dmatimings[mode & ATA_MODE_MASK] << offset), 4);
	    piomode = (mode == ATA_WDMA0) ? ATA_PIO0 :
		(mode == ATA_WDMA1) ? ATA_PIO3 : ATA_PIO4;
	} else {
	    /* Disable UDMA, set requested PIO. */
	    pci_write_config(gparent, 0x54,
			     pci_read_config(gparent, 0x54, 1) &
			     ~(0x01 << devno), 1);
	    piomode = mode;
	}
	/* Set PIO mode and timings, calculated above. */
	pci_write_config(gparent, 0x4a,
			 (pci_read_config(gparent, 0x4a, 2) &
			  ~(0xf << (devno << 2))) |
			 ((piomode - ATA_PIO0) << (devno<<2)),2);
	pci_write_config(gparent, 0x40,
			 (pci_read_config(gparent, 0x40, 4) &
			  ~(0xff << offset)) |
			 (piotimings[ata_mode2idx(piomode)] << offset), 4);
	atadev->mode = mode;
    }
}