summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2006-02-10 21:45:42 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2006-02-10 21:45:42 +0000
commit09a2ff51b5828572f0e19cfdaa8b69cb6a6ff4c0 (patch)
treea775b627eedd69dcfd6da75044448513d7cf793c /sys/dev/ic
parentbd5c3bbd6c5540e95267d39fc4ec4baaed36b9c1 (diff)
Fix LBA48 access for ServerWorks SATA.
ok grange@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/wdc.c30
-rw-r--r--sys/dev/ic/wdcvar.h9
2 files changed, 28 insertions, 11 deletions
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 62599e113bf..4a19590d8f6 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc.c,v 1.88 2005/11/09 19:05:48 uwe Exp $ */
+/* $OpenBSD: wdc.c,v 1.89 2006/02/10 21:45:41 kettenis Exp $ */
/* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */
@@ -140,6 +140,7 @@ int wdc_ata_present(struct channel_softc *, int);
struct channel_softc_vtbl wdc_default_vtbl = {
wdc_default_read_reg,
wdc_default_write_reg,
+ wdc_default_lba48_write_reg,
wdc_default_read_raw_multi_2,
wdc_default_write_raw_multi_2,
wdc_default_read_raw_multi_4,
@@ -334,6 +335,16 @@ wdc_default_write_reg(chp, reg, val)
reg & _WDC_REGMASK, val);
}
+void
+wdc_default_lba48_write_reg(chp, reg, val)
+ struct channel_softc *chp;
+ enum wdc_regs reg;
+ u_int16_t val;
+{
+ /* All registers are two byte deep FIFOs. */
+ CHP_WRITE_REG(chp, reg, val >> 8);
+ CHP_WRITE_REG(chp, reg, val);
+}
void
wdc_default_read_raw_multi_2(chp, data, nbytes)
@@ -1956,15 +1967,14 @@ wdccommandext(chp, drive, command, blkno, count)
/* Select drive and LBA mode. */
CHP_WRITE_REG(chp, wdr_sdh, (drive << 4) | WDSD_LBA);
- /* Load parameters. All registers are two byte deep FIFOs. */
- CHP_WRITE_REG(chp, wdr_lba_hi, blkno >> 40);
- CHP_WRITE_REG(chp, wdr_lba_hi, blkno >> 16);
- CHP_WRITE_REG(chp, wdr_lba_mi, blkno >> 32);
- CHP_WRITE_REG(chp, wdr_lba_mi, blkno >> 8);
- CHP_WRITE_REG(chp, wdr_lba_lo, blkno >> 24);
- CHP_WRITE_REG(chp, wdr_lba_lo, blkno);
- CHP_WRITE_REG(chp, wdr_seccnt, count >> 8);
- CHP_WRITE_REG(chp, wdr_seccnt, count);
+ /* Load parameters. */
+ CHP_LBA48_WRITE_REG(chp, wdr_lba_hi,
+ ((blkno >> 32) & 0xff00) | ((blkno >> 16) & 0xff));
+ CHP_LBA48_WRITE_REG(chp, wdr_lba_mi,
+ ((blkno >> 24) & 0xff00) | ((blkno >> 8) & 0xff));
+ CHP_LBA48_WRITE_REG(chp, wdr_lba_lo,
+ ((blkno >> 16) & 0xff00) | (blkno & 0xff));
+ CHP_LBA48_WRITE_REG(chp, wdr_seccnt, count);
/* Send command. */
CHP_WRITE_REG(chp, wdr_command, command);
diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h
index d87e15a16a7..9b8d4ef6fbb 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdcvar.h,v 1.37 2004/10/17 17:50:48 grange Exp $ */
+/* $OpenBSD: wdcvar.h,v 1.38 2006/02/10 21:45:41 kettenis Exp $ */
/* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */
/*-
@@ -121,6 +121,8 @@ struct channel_softc_vtbl {
u_int8_t (*read_reg)(struct channel_softc *, enum wdc_regs reg);
void (*write_reg)(struct channel_softc *, enum wdc_regs reg,
u_int8_t var);
+ void (*lba48_write_reg)(struct channel_softc *, enum wdc_regs reg,
+ u_int16_t var);
void (*read_raw_multi_2)(struct channel_softc *,
void *data, unsigned int nbytes);
@@ -136,6 +138,9 @@ struct channel_softc_vtbl {
#define CHP_READ_REG(chp, a) ((chp)->_vtbl->read_reg)(chp, a)
#define CHP_WRITE_REG(chp, a, b) ((chp)->_vtbl->write_reg)(chp, a, b)
+#define CHP_LBA48_WRITE_REG(chp, a, b) \
+ ((chp)->_vtbl->lba48_write_reg)(chp, a, b)
+
#define CHP_READ_RAW_MULTI_2(chp, a, b) \
((chp)->_vtbl->read_raw_multi_2)(chp, a, b)
#define CHP_WRITE_RAW_MULTI_2(chp, a, b) \
@@ -316,6 +321,8 @@ u_int8_t wdc_default_read_reg(struct channel_softc *,
enum wdc_regs);
void wdc_default_write_reg(struct channel_softc *,
enum wdc_regs, u_int8_t);
+void wdc_default_lba48_write_reg(struct channel_softc *,
+ enum wdc_regs, u_int16_t);
void wdc_default_read_raw_multi_2(struct channel_softc *,
void *, unsigned int);
void wdc_default_write_raw_multi_2(struct channel_softc *,