Add support for LBA48 read command to standalone wdc/wd driver.
Thanks to bouyer@ for comments about LBA48 boundary checks. Tested on: > Cobalt Qube 2700 > wd0 at atabus0 drive 0: <Hitachi HDS721616PLA380> > wd0: 153 GB, 319120 cyl, 16 head, 63 sec, 512 bytes/sect x 321672960 sectors via SATA-IDE converter, and NetBSD partition allocated at: > 1: NetBSD (sysid 169) > start 293603940, size 28069020 (13706 MB, Cyls 18276-20023/54/63) Also bump version.
This commit is contained in:
parent
a11ec02c51
commit
f204082a1d
@ -1,4 +1,4 @@
|
||||
$NetBSD: version,v 1.10 2008/05/28 14:04:07 tsutsui Exp $
|
||||
$NetBSD: version,v 1.11 2010/01/10 16:20:45 tsutsui Exp $
|
||||
|
||||
NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this
|
||||
file is important - make sure the entries are appended on end, last item
|
||||
@ -14,3 +14,4 @@ is taken as the current.
|
||||
0.7: Add support for netboot via 21041 on Qube2700
|
||||
0.8: Add support for optional Z85C30 serial console on Qube2700
|
||||
0.9: Print banner and a loading kernel name onto LCD
|
||||
1.0: Add support for LBA48 read command
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wd.c,v 1.10 2008/04/28 20:23:16 martin Exp $ */
|
||||
/* $NetBSD: wd.c,v 1.11 2010/01/10 16:20:45 tsutsui Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -61,18 +61,45 @@ wd_get_params(struct wd_softc *wd)
|
||||
wd->sc_params = *(struct ataparams *)buf;
|
||||
|
||||
/* 48-bit LBA addressing */
|
||||
if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0) {
|
||||
DPRINTF(("Drive supports LBA48.\n"));
|
||||
#if defined(_ENABLE_LBA48)
|
||||
if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0)
|
||||
wd->sc_flags |= WDF_LBA48;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prior to ATA-4, LBA was optional. */
|
||||
if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) {
|
||||
DPRINTF(("Drive supports LBA.\n"));
|
||||
if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
|
||||
wd->sc_flags |= WDF_LBA;
|
||||
|
||||
if ((wd->sc_flags & WDF_LBA48) != 0) {
|
||||
DPRINTF(("Drive supports LBA48.\n"));
|
||||
wd->sc_capacity =
|
||||
((uint64_t)wd->sc_params.atap_max_lba[3] << 48) |
|
||||
((uint64_t)wd->sc_params.atap_max_lba[2] << 32) |
|
||||
((uint64_t)wd->sc_params.atap_max_lba[1] << 16) |
|
||||
((uint64_t)wd->sc_params.atap_max_lba[0] << 0);
|
||||
DPRINTF(("atap_max_lba = (0x%x, 0x%x, 0x%x, 0x%x)\n",
|
||||
wd->sc_params.atap_max_lba[3],
|
||||
wd->sc_params.atap_max_lba[2],
|
||||
wd->sc_params.atap_max_lba[1],
|
||||
wd->sc_params.atap_max_lba[0]));
|
||||
wd->sc_capacity28 =
|
||||
((uint32_t)wd->sc_params.atap_capacity[1] << 16) |
|
||||
((uint32_t)wd->sc_params.atap_capacity[0] << 0);
|
||||
DPRINTF(("atap_capacity = (0x%x, 0x%x)\n",
|
||||
wd->sc_params.atap_capacity[1],
|
||||
wd->sc_params.atap_capacity[0]));
|
||||
} else if ((wd->sc_flags & WDF_LBA) != 0) {
|
||||
DPRINTF(("Drive supports LBA.\n"));
|
||||
wd->sc_capacity = wd->sc_capacity28 =
|
||||
((uint32_t)wd->sc_params.atap_capacity[1] << 16) |
|
||||
((uint32_t)wd->sc_params.atap_capacity[0] << 0);
|
||||
} else {
|
||||
DPRINTF(("Drive doesn't support LBA; using CHS.\n"));
|
||||
wd->sc_capacity = wd->sc_capacity28 =
|
||||
wd->sc_params.atap_cylinders *
|
||||
wd->sc_params.atap_heads *
|
||||
wd->sc_params.atap_sectors;
|
||||
}
|
||||
DPRINTF(("wd->sc_capacity = %ld, wd->sc_capacity28 = %d.\n",
|
||||
(u_long)wd->sc_capacity, wd->sc_capacity28));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -173,7 +200,7 @@ wdgetdisklabel(struct wd_softc *wd)
|
||||
}
|
||||
|
||||
DPRINTF(("label info: d_secsize %d, d_nsectors %d, d_ncylinders %d,"
|
||||
"d_ntracks %d, d_secpercyl %d\n",
|
||||
" d_ntracks %d, d_secpercyl %d\n",
|
||||
wd->sc_label.d_secsize,
|
||||
wd->sc_label.d_nsectors,
|
||||
wd->sc_label.d_ncylinders,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc.c,v 1.11 2008/04/28 20:23:16 martin Exp $ */
|
||||
/* $NetBSD: wdc.c,v 1.12 2010/01/10 16:20:45 tsutsui Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -229,7 +229,7 @@ wdccommand(struct wd_softc *sc, struct wdc_command *wd_c)
|
||||
wd_c->r_precomp));
|
||||
#endif
|
||||
|
||||
WDC_WRITE_REG(chp, wd_precomp, wd_c->r_precomp);
|
||||
WDC_WRITE_REG(chp, wd_features, wd_c->r_features);
|
||||
WDC_WRITE_REG(chp, wd_seccnt, wd_c->r_count);
|
||||
WDC_WRITE_REG(chp, wd_sector, wd_c->r_sector);
|
||||
WDC_WRITE_REG(chp, wd_cyl_lo, wd_c->r_cyl);
|
||||
@ -258,6 +258,12 @@ wdccommandext(struct wd_softc *wd, struct wdc_command *wd_c)
|
||||
{
|
||||
struct wdc_channel *chp = &wd->sc_channel;
|
||||
|
||||
#if 0
|
||||
DPRINTF(("%s(%d, %x, %ld, %d)\n", __func__,
|
||||
wd_c->drive, wd_c->r_command,
|
||||
(u_long)wd_c->r_blkno, wd_c->r_count));
|
||||
#endif
|
||||
|
||||
/* Select drive, head, and addressing mode. */
|
||||
WDC_WRITE_REG(chp, wd_sdh, (wd_c->drive << 4) | WDSD_LBA);
|
||||
|
||||
@ -320,20 +326,37 @@ wdc_exec_read(struct wd_softc *wd, uint8_t cmd, daddr_t blkno, void *data)
|
||||
{
|
||||
int error;
|
||||
struct wdc_command wd_c;
|
||||
bool lba, lba48;
|
||||
|
||||
memset(&wd_c, 0, sizeof(wd_c));
|
||||
lba = false;
|
||||
lba48 = false;
|
||||
|
||||
if (wd->sc_flags & WDF_LBA48) {
|
||||
wd_c.data = data;
|
||||
wd_c.r_count = 1;
|
||||
wd_c.r_features = 0;
|
||||
wd_c.drive = wd->sc_unit;
|
||||
wd_c.bcount = wd->sc_label.d_secsize;
|
||||
|
||||
if ((wd->sc_flags & WDF_LBA48) != 0 && blkno > wd->sc_capacity28)
|
||||
lba48 = true;
|
||||
else if ((wd->sc_flags & WDF_LBA) != 0)
|
||||
lba = true;
|
||||
|
||||
if (lba48) {
|
||||
/* LBA48 */
|
||||
wd_c.r_command = atacmd_to48(cmd);
|
||||
wd_c.r_blkno = blkno;
|
||||
} else if (wd->sc_flags & WDF_LBA) {
|
||||
} else if (lba) {
|
||||
/* LBA */
|
||||
wd_c.r_command = cmd;
|
||||
wd_c.r_sector = (blkno >> 0) & 0xff;
|
||||
wd_c.r_cyl = (blkno >> 8) & 0xffff;
|
||||
wd_c.r_head = (blkno >> 24) & 0x0f;
|
||||
wd_c.r_head |= WDSD_LBA;
|
||||
} else {
|
||||
/* LHS */
|
||||
/* CHS */
|
||||
wd_c.r_command = cmd;
|
||||
wd_c.r_sector = blkno % wd->sc_label.d_nsectors;
|
||||
wd_c.r_sector++; /* Sectors begin with 1, not 0. */
|
||||
blkno /= wd->sc_label.d_nsectors;
|
||||
@ -343,13 +366,7 @@ wdc_exec_read(struct wd_softc *wd, uint8_t cmd, daddr_t blkno, void *data)
|
||||
wd_c.r_head |= WDSD_CHS;
|
||||
}
|
||||
|
||||
wd_c.data = data;
|
||||
wd_c.r_count = 1;
|
||||
wd_c.drive = wd->sc_unit;
|
||||
wd_c.r_command = cmd;
|
||||
wd_c.bcount = wd->sc_label.d_secsize;
|
||||
|
||||
if (wd->sc_flags & WDF_LBA48)
|
||||
if (lba48)
|
||||
error = wdccommandext(wd, &wd_c);
|
||||
else
|
||||
error = wdccommand(wd, &wd_c);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdvar.h,v 1.8 2007/10/17 19:54:10 garbled Exp $ */
|
||||
/* $NetBSD: wdvar.h,v 1.9 2010/01/10 16:20:45 tsutsui Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -72,6 +72,7 @@ struct wd_softc {
|
||||
u_int sc_unit;
|
||||
|
||||
uint64_t sc_capacity;
|
||||
uint32_t sc_capacity28;
|
||||
|
||||
struct ataparams sc_params;
|
||||
struct disklabel sc_label;
|
||||
@ -86,7 +87,7 @@ struct wdc_command {
|
||||
uint16_t r_cyl;
|
||||
uint8_t r_sector;
|
||||
uint8_t r_count;
|
||||
uint8_t r_precomp;
|
||||
uint8_t r_features;
|
||||
|
||||
uint16_t bcount;
|
||||
void *data;
|
||||
|
Loading…
Reference in New Issue
Block a user