tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Sending ATA commands?
I don't know if anyone remembers enough of 5.x or 4.x to help with
this, but if anyone does and cares to comment....
Prompted by seeing a Linux dmesg saying "Host Protected Area detected",
I started trying to teach NetBSD about HPA. (If I can make this work,
DCO support is next.)
I found a PDF describing the relevant command set up for fetch at
http://pdos.csail.mit.edu/6.828/2005/readings/hardware/ATA-d1410r3a.pdf.
But I'm fairly sure I'm doing something wrong, because it's returning
obviously-garbage results.
I have a device whose IDENTIFY DEVICE response indicates HPA support,
according to
if ( (wd->sc_params.atap_cmd_set1 != 0x0000) &&
(wd->sc_params.atap_cmd_set1 != 0xffff) &&
(wd->sc_params.atap_cmd_set1 & WDC_CMD1_HPA) )
But the code I wrote that tries to use the READ NATIVE MAX ADDRESS
command doesn't seem to work. (The drive is only some 8G, not large
enough to need READ NATIVE MAX ADDRESS EXT - and if it's a much larger
drive being HPA-limited for some reason, READ NATIVE MAX ADDRESS is
supposed to return 0xfffffff). The usual code reports the drive as
having 18039071 sectors, but my attempt to use READ NATIVE MAX ADDRESS
returns a size of 4581695 - completely ludicrous in view of IDENTIFY
DEVICE returning a number nearly four times as large.
Here's the code I added. I based on it sys/dev/ata/wd.c 1.335.2.1.4.1,
ie, 4.0.1's, largely because that's what was running on the handiest
scratch machine.
static void hpa_check(struct device *self)
{
struct wd_softc *wd;
struct ata_command cmd;
unsigned int cap;
wd = (void *) self;
aprint_normal("%s: HPA supported",&self->dv_xname[0]);
if (wd->sc_params.atap_cmd1_en & WDC_CMD1_HPA)
{ aprint_normal(", HPA present");
}
else
{ aprint_normal(", no HPA");
}
if (wd->sc_params.atap_cmd_set2 & 0x80) /* XXX no WDC_* bit */
{ aprint_normal(", offset supported\n");
}
aprint_normal("\n");
bzero(&cmd,sizeof(cmd));
cmd.r_command = 0xf8; /* XXX no WDCC_ define */
cmd.r_st_bmask = 0;
cmd.r_st_pmask = 0;
cmd.r_features = 0;
cmd.r_count = 0;
cmd.timeout = 1000;
cmd.flags = AT_WAIT | AT_READREG;
cmd.data = 0;
cmd.bcount = 0;
if ((*((struct ata_channel
*)wd->drvp->chnl_softc)->ch_atac->atac_bustype_ata->ata_exec_command)(wd->drvp,&cmd)
!= ATACMD_COMPLETE)
{ aprint_normal("%s: READ NATIVE MAX ADDRESS failed\n",&self->dv_xname[0]);
}
else
{ cap = cmd.r_sector | (cmd.r_cyl * 256) | ((cmd.r_head & 0xf) * 0x1000000);
aprint_normal("%s: READ NATIVE MAX ADDRESS returned
%u\n",&self->dv_xname[0],cap);
}
}
This is called from wdattach just after printing the addressing method:
if ((wd->sc_flags & WDF_LBA48) != 0) {
aprint_normal(" LBA48 addressing\n");
[...]
} else if ((wd->sc_flags & WDF_LBA) != 0) {
aprint_normal(" LBA addressing\n");
[...]
} else {
aprint_normal(" chs addressing\n");
[...]
}
if ( (wd->sc_params.atap_cmd_set1 != 0x0000) &&
(wd->sc_params.atap_cmd_set1 != 0xffff) &&
(wd->sc_params.atap_cmd_set1 & WDC_CMD1_HPA) )
hpa_check(self);
and I'm seeing
wd0 at atabus0 drive 0: <QUANTUM FIREBALLP KA9.1>
wd0: drive supports 16-sector PIO transfers, LBA addressing
wd0: HPA supported, HPA present
wd0: READ NATIVE MAX ADDRESS returned 4581695
wd0: 8808 MB, 17895 cyl, 16 head, 63 sec, 512 bytes/sect x 18039071 sectors
I notice that I'm not getting zero (which is what I'd expect if it
weren't reading back registers), nor am I just losing the top bits, nor
am I getting something that (possibly after correcting for missing high
bits) is just a little greater than the IDENTIFY-reported capacity. So
I assume I'm doing something wrong, and the obvious question is, what?
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse%rodents-montreal.org@localhost
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Home |
Main Index |
Thread Index |
Old Index