summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJason Downs <downsj@cvs.openbsd.org>1996-08-07 01:56:30 +0000
committerJason Downs <downsj@cvs.openbsd.org>1996-08-07 01:56:30 +0000
commit8f2506ae6e53c6e60bb719e41e203a97a5a5a9bd (patch)
treeca0a86713deb7a0bec6e305882164efa69cc551e /sys
parentd5011bdf9d47ce16a5dd7f52ea0b46f5e60b3664 (diff)
bus.h using ATAPI, by niklas, plus a quirk table and some small fixes by me.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/atapi/acd.c136
-rw-r--r--sys/dev/atapi/atapiconf.c131
-rw-r--r--sys/dev/atapi/atapilink.h13
3 files changed, 193 insertions, 87 deletions
diff --git a/sys/dev/atapi/acd.c b/sys/dev/atapi/acd.c
index cc7757e17bc..acebbed28f0 100644
--- a/sys/dev/atapi/acd.c
+++ b/sys/dev/atapi/acd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acd.c,v 1.7 1996/08/06 22:41:00 downsj Exp $ */
+/* $OpenBSD: acd.c,v 1.8 1996/08/07 01:56:27 downsj Exp $ */
/*
* Copyright (c) 1996 Manuel Bouyer. All rights reserved.
@@ -110,12 +110,25 @@ struct cfdriver acd_cd = {
void acdgetdisklabel __P((struct acd_softc *));
int acd_get_parms __P((struct acd_softc *, int));
void acdstrategy __P((struct buf *));
-void acdstart __P((struct acd_softc *));
+void acdstart __P((void *));
int acd_pause __P((struct acd_softc *, int));
void acdminphys __P((struct buf*));
u_long acd_size __P((struct acd_softc*, int));
-int acddone __P((struct atapi_command_packet *));
-int acd_get_mode __P((struct acd_softc *, struct atapi_mode_data *, int, int, int));
+int acddone __P((void *));
+#ifndef XXX
+int acdlock __P((struct acd_softc *));
+void acdunlock __P((struct acd_softc *));
+int acdopen __P((dev_t, int, int));
+int acdclose __P((dev_t, int, int));
+int acdread __P((dev_t, struct uio*));
+int acdwrite __P((dev_t, struct uio*));
+int acdioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
+int acd_reset __P((struct acd_softc *));
+int acdsize __P((dev_t));
+int acddump __P((dev_t, daddr_t, caddr_t, size_t));
+#endif
+int acd_get_mode __P((struct acd_softc *, struct atapi_mode_data *, int,
+ int, int));
int acd_set_mode __P((struct acd_softc *, struct atapi_mode_data *, int));
int acd_setchan __P((struct acd_softc *, u_char, u_char, u_char, u_char));
int acd_play __P((struct acd_softc *, int, int));
@@ -123,10 +136,12 @@ int acd_play_big __P((struct acd_softc *, int, int));
int acd_load_toc __P((struct acd_softc *, struct cd_toc *));
int acd_play_tracks __P((struct acd_softc *, int, int, int, int));
int acd_play_msf __P((struct acd_softc *, int, int, int, int, int, int));
-int acd_read_subchannel __P((struct acd_softc *, int, int, int, struct cd_sub_channel_info *, int));
+int acd_read_subchannel __P((struct acd_softc *, int, int, int,
+ struct cd_sub_channel_info *, int));
int acd_read_toc __P((struct acd_softc *, int, int, void *, int));
-u_long msf2lba __P((u_char, u_char, u_char ));
-
+static void lba2msf __P((u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *));
+static __inline u_int32_t msf2lba __P((u_int8_t, u_int8_t, u_int8_t));
+static __inline void bswap __P((u_int8_t *, int));
struct dkdriver acddkdriver = { acdstrategy };
@@ -139,7 +154,6 @@ acdmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct cfdata *cf = match;
struct at_dev_link *sa = aux;
#ifdef ATAPI_DEBUG_PROBE
@@ -147,12 +161,8 @@ acdmatch(parent, match, aux)
sa->id.config.device_type & ATAPI_DEVICE_TYPE_MASK);
#endif
- /* XXX!!! */
if (((sa->id.config.device_type & ATAPI_DEVICE_TYPE_MASK) ==
- ATAPI_DEVICE_TYPE_CD) ||
- (((sa->id.config.device_type & ATAPI_DEVICE_TYPE_MASK) ==
- ATAPI_DEVICE_TYPE_DAD) &&
- (sa->id.config.cmd_drq_rem & ATAPI_REMOVABLE)))
+ ATAPI_DEVICE_TYPE_CD) || (sa->quirks & ADEV_CDROM))
return 1;
return 0;
}
@@ -311,7 +321,7 @@ acdopen(dev, flag, fmt)
ad_link->flags |= ADEV_OPEN;
/* Lock the pack in. */
- if (error = atapi_prevent(ad_link, PR_PREVENT))
+ if ((error = atapi_prevent(ad_link, PR_PREVENT)) != 0)
goto bad;
if ((ad_link->flags & ADEV_MEDIA_LOADED) == 0) {
@@ -504,9 +514,10 @@ done:
* cdstart() is called at splbio from cdstrategy and atapi_done
*/
void
-acdstart(acd)
- struct acd_softc *acd;
+acdstart(vp)
+ void *vp;
{
+ struct acd_softc *acd = vp;
struct at_dev_link *ad_link;
struct buf *bp = 0;
struct buf *dp;
@@ -609,8 +620,10 @@ acdstart(acd)
* Call the routine that chats with the adapter.
* Note: we cannot sleep as we may be an interrupt
*/
- if (atapi_exec_io(ad_link, &cmd, sizeof(cmd), bp, A_NOSLEEP))
+ if (atapi_exec_io(ad_link, &cmd, sizeof(cmd), bp, A_NOSLEEP)) {
+ disk_unbusy(&acd->sc_dk, 0);
printf("%s: not queued", acd->sc_dev.dv_xname);
+ }
}
}
@@ -636,12 +649,12 @@ acdwrite(dev, uio)
* conversion between minute-seconde-frame and logical block adress
* adresses format
*/
-void
+static void
lba2msf (lba, m, s, f)
- u_long lba;
- u_char *m, *s, *f;
+ u_int32_t lba;
+ u_int8_t *m, *s, *f;
{
- u_long tmp;
+ u_int32_t tmp;
tmp = lba + CD_BLOCK_OFFSET; /* offset of first logical frame */
tmp &= 0xffffff; /* negative lbas use only 24 bits */
*m = tmp / (CD_SECS * CD_FRAMES);
@@ -650,13 +663,24 @@ lba2msf (lba, m, s, f)
*f = tmp % CD_FRAMES;
}
-u_long
+static __inline u_int32_t
msf2lba (m, s, f)
- u_char m, s, f;
+ u_int8_t m, s, f;
{
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_BLOCK_OFFSET;
}
+static __inline void
+bswap (buf, len)
+ u_int8_t *buf;
+ int len;
+{
+ u_int16_t *p = (u_int16_t *)(buf + len);
+
+ while (--p >= (u_int16_t *)buf)
+ *p = (*p & 0xff) << 8 | (*p >> 8 & 0xff);
+}
+
/*
* Perform special action on behalf of the user.
* Knows about the internals of this device
@@ -694,7 +718,7 @@ acdioctl(dev, cmd, addr, flag, p)
if ((flag & FWRITE) == 0)
return EBADF;
- if (error = acdlock(acd))
+ if ((error = acdlock(acd)) != 0)
return error;
acd->flags |= CDF_LABELLING;
@@ -744,23 +768,31 @@ acdioctl(dev, cmd, addr, flag, p)
len < sizeof(struct cd_sub_channel_header))
return EINVAL;
- if (error = acd_read_subchannel(acd, args->address_format,
- args->data_format, args->track,
- &data, len))
+ error = acd_read_subchannel(acd, args->address_format,
+ args->data_format, args->track, &data, len);
+ if (error)
return error;
return copyout(&data, args->data, len);
}
+ /* XXX Remove endian dependency */
case CDIOREADTOCHEADER: {
struct ioc_toc_header hdr;
- if (error = acd_read_toc(acd, 0, 0, &hdr, sizeof(hdr)))
+ error = acd_read_toc(acd, 0, 0, &hdr, sizeof(hdr));
+ if (error)
return error;
- hdr.len = ntohs(hdr.len);
+ if (acd->ad_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t *)&hdr.len, sizeof(hdr.len));
+#endif
+ } else
+ hdr.len = ntohs(hdr.len);
bcopy(&hdr, addr, sizeof(hdr));
return 0;
}
+ /* XXX Remove endian dependency */
case CDIOREADTOCENTRYS: {
struct ioc_read_toc_entry *te =
(struct ioc_read_toc_entry *)addr;
@@ -773,20 +805,30 @@ acdioctl(dev, cmd, addr, flag, p)
len < sizeof(struct cd_toc_entry))
return EINVAL;
- if (error = acd_read_toc(acd, te->address_format,
- te->starting_track, &toc,
- len + sizeof(struct ioc_toc_header)))
+ error = acd_read_toc(acd, te->address_format,
+ te->starting_track, &toc,
+ len + sizeof(struct ioc_toc_header));
+ if (error)
return error;
if (te->address_format == CD_LBA_FORMAT) {
for (ntracks = th->ending_track - th->starting_track + 1;
ntracks >= 0; ntracks--) {
toc.tab[ntracks].addr_type = CD_LBA_FORMAT;
- (u_int32_t)(*toc.tab[ntracks].addr.addr) =
- ntohl((u_int32_t)(*toc.tab[ntracks].addr.addr));
+ if (acd->ad_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&toc.tab[ntracks].addr.addr, sizeof(toc.tab[ntracks].addr.addr));
+#endif
+ } else
+ (u_int32_t)(*toc.tab[ntracks].addr.addr) = ntohl((u_int32_t)(*toc.tab[ntracks].addr.addr));
}
}
- th->len = ntohs(th->len);
+ if (acd->ad_link->quirks & ADEV_LITTLETOC) {
+#if BYTE_ORDER == BIG_ENDIAN
+ bswap((u_int8_t*)&th->len, sizeof(th->len));
+#endif
+ } else
+ th->len = ntohs(th->len);
len = min(len, th->len - sizeof(struct ioc_toc_header));
return copyout(toc.tab, te->data, len);
@@ -802,8 +844,9 @@ acdioctl(dev, cmd, addr, flag, p)
case CDIOCGETVOL: {
struct ioc_vol *arg = (struct ioc_vol *)addr;
struct atapi_mode_data data;
- if (error = acd_get_mode(acd, &data, ATAPI_AUDIO_PAGE,
- AUDIOPAGESIZE, 0))
+ error = acd_get_mode(acd, &data, ATAPI_AUDIO_PAGE,
+ AUDIOPAGESIZE, 0);
+ if (error)
return error;
arg->vol[0] = data.page_audio.port[0].volume;
arg->vol[1] = data.page_audio.port[1].volume;
@@ -816,12 +859,14 @@ acdioctl(dev, cmd, addr, flag, p)
struct ioc_vol *arg = (struct ioc_vol *)addr;
struct atapi_mode_data data, mask;
- if (error = acd_get_mode(acd, &data, ATAPI_AUDIO_PAGE,
- AUDIOPAGESIZE, 0))
+ error = acd_get_mode(acd, &data, ATAPI_AUDIO_PAGE,
+ AUDIOPAGESIZE, 0);
+ if (error)
return error;
- if (error = acd_get_mode(acd, &mask, ATAPI_AUDIO_PAGE_MASK,
- AUDIOPAGESIZE, 0))
+ error = acd_get_mode(acd, &mask, ATAPI_AUDIO_PAGE_MASK,
+ AUDIOPAGESIZE, 0);
+ if (error)
return error;
data.page_audio.port[0].volume = arg->vol[0] &
@@ -982,12 +1027,12 @@ acd_size(cd, flags)
return 0;
}
- blksize = ntohl(rdcap.blksize);
+ blksize = _4btol((u_int8_t*)&rdcap.blksize);
if (blksize < 512)
blksize = 2048; /* some drives lie ! */
cd->params.blksize = blksize;
- size = ntohl(rdcap.size);
+ size = _4btol((u_int8_t*)&rdcap.size);
if (size < 100)
size = 400000; /* ditto */
cd->params.disksize = size;
@@ -1331,9 +1376,10 @@ acddump(dev, blkno, va, size)
}
int
-acddone(acp)
- struct atapi_command_packet *acp;
+acddone(vp)
+ void *vp;
{
+ struct atapi_command_packet *acp = vp;
struct at_dev_link *ad_link = acp->ad_link;
struct acd_softc *acd = ad_link->device_softc;
diff --git a/sys/dev/atapi/atapiconf.c b/sys/dev/atapi/atapiconf.c
index ec5bb34d984..334bd34a6d5 100644
--- a/sys/dev/atapi/atapiconf.c
+++ b/sys/dev/atapi/atapiconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atapiconf.c,v 1.4 1996/07/22 03:35:42 downsj Exp $ */
+/* $OpenBSD: atapiconf.c,v 1.5 1996/08/07 01:56:28 downsj Exp $ */
/*
* Copyright (c) 1996 Manuel Bouyer. All rights reserved.
@@ -61,8 +61,8 @@ struct atapibus_softc {
LIST_HEAD(pkt_free_list, atapi_command_packet) pkt_free_list;
-static void bswap __P((char *, int));
-static void btrim __P((char *, int));
+static __inline void bswap __P((char *, int));
+static __inline void btrim __P((char *, int));
int atapi_error __P((struct atapi_command_packet *));
void atapi_sense __P((struct atapi_command_packet *, u_int8_t, u_int8_t));
@@ -70,6 +70,8 @@ void at_print_addr __P((struct at_dev_link *, u_int8_t));
int atapibusmatch __P((struct device *, void *, void *));
void atapibusattach __P((struct device *, struct device *, void *));
+void atapi_fixquirk __P((struct at_dev_link *));
+int atapiprint __P((void *, char *));
struct cfattach atapibus_ca = {
sizeof(struct atapibus_softc), atapibusmatch, atapibusattach
@@ -80,12 +82,30 @@ struct cfdriver atapibus_cd = {
};
+/*
+ * ATAPI quirk table support.
+ */
+
+struct atapi_quirk_inquiry_pattern {
+ struct {
+ u_int8_t type;
+ u_int8_t rem;
+ char *product;
+ char *revision;
+ } pattern;
+ u_int8_t quirks;
+};
+
+struct atapi_quirk_inquiry_pattern atapi_quirk_inquiry_patterns[] = {
+ {{ATAPI_DEVICE_TYPE_CD, ATAPI_REMOVABLE,
+ "GCD-R580B", "1.00"}, ADEV_LITTLETOC},
+};
+
int
atapibusmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
- struct cfdata *cf = match;
struct bus_link *ab_link = aux;
if (ab_link == NULL)
@@ -95,6 +115,56 @@ atapibusmatch(parent, match, aux)
return 1;
}
+void
+atapi_fixquirk(ad_link)
+ struct at_dev_link *ad_link;
+{
+ struct atapi_identify *id = &ad_link->id;
+ struct atapi_quirk_inquiry_pattern *finger;
+ int quirk, nquirks;
+
+ /*
+ * Shuffle string byte order.
+ * Mitsumi and NEC drives don't need this.
+ */
+ if (((id->model[0] == 'N' && id->model[1] == 'E') ||
+ (id->model[0] == 'F' && id->model[1] == 'X')) == 0)
+ bswap(id->model, sizeof(id->model));
+ bswap(id->serial_number, sizeof(id->serial_number));
+ bswap(id->firmware_revision, sizeof(id->firmware_revision));
+
+ /*
+ * Clean up the model name, serial and
+ * revision numbers.
+ */
+ btrim(id->model, sizeof(id->model));
+ btrim(id->serial_number, sizeof(id->serial_number));
+ btrim(id->firmware_revision, sizeof(id->firmware_revision));
+
+ nquirks = sizeof(atapi_quirk_inquiry_patterns) /
+ sizeof(struct atapi_quirk_inquiry_pattern);
+ for (quirk = 0; quirk < nquirks; quirk++) {
+ finger = &atapi_quirk_inquiry_patterns[quirk];
+
+ if ((id->config.device_type
+ & ATAPI_DEVICE_TYPE_MASK) != finger->pattern.type)
+ continue;
+ if ((id->config.cmd_drq_rem & finger->pattern.rem) == 0)
+ continue;
+ if (strcmp(id->model, finger->pattern.product))
+ continue;
+ if (strcmp(id->firmware_revision, finger->pattern.revision))
+ continue;
+
+ break;
+ }
+
+ if (quirk < nquirks) {
+ /* Found a quirk entry for this drive. */
+ ad_link->quirks = finger->quirks;
+ }
+}
+
int
atapiprint(aux, bus)
void *aux;
@@ -128,37 +198,21 @@ atapiprint(aux, bus)
fixrem = (id->config.cmd_drq_rem & ATAPI_REMOVABLE) ?
"removable" : "fixed";
- /*
- * Shuffle string byte order.
- * Mitsumi and NEC drives don't need this.
- */
- if (((id->model[0] == 'N' && id->model[1] == 'E') ||
- (id->model[0] == 'F' && id->model[1] == 'X')) == 0)
- bswap(id->model, sizeof(id->model));
-
- /*
- * XXX Poorly named... These appear to actually be in
- * XXX network byte order, so bswap() is a no-op on
- * XXX big-endian hosts. Clean me up, please.
- */
- bswap(id->serial_number, sizeof(id->serial_number));
- bswap(id->firmware_revision, sizeof(id->firmware_revision));
-
- /*
- * Clean up the model name, serial and
- * revision numbers.
- */
- btrim(id->model, sizeof(id->model));
- btrim(id->serial_number, sizeof(id->serial_number));
- btrim(id->firmware_revision, sizeof(id->firmware_revision));
-
if (bus != NULL)
printf("%s", bus);
- printf(" drive %d: <%s, %s, %s> ATAPI %d/%s %s",
- ad_link->drive, id->model, id->serial_number,
- id->firmware_revision,
- id->config.device_type & ATAPI_DEVICE_TYPE_MASK, dtype, fixrem);
+ if (id->serial_number[0]) {
+ printf(" drive %d: <%s, %s, %s> ATAPI %d/%s %s",
+ ad_link->drive, id->model, id->serial_number,
+ id->firmware_revision,
+ (id->config.device_type & ATAPI_DEVICE_TYPE_MASK),
+ dtype, fixrem);
+ } else {
+ printf(" drive %d: <%s, %s> ATAPI %d/%s %s",
+ ad_link->drive, id->model, id->firmware_revision,
+ (id->config.device_type & ATAPI_DEVICE_TYPE_MASK),
+ dtype, fixrem);
+ }
return UNCONF;
}
@@ -211,6 +265,9 @@ atapibusattach(parent, self, aux)
ad_link->bus = ab_link_proto;
bcopy(id, &ad_link->id, sizeof(*id));
+ /* Fix strings and look through the quirk table. */
+ atapi_fixquirk(ad_link);
+
/* Try to find a match. */
if (config_found(self, ad_link, atapiprint) == NULL)
free(ad_link, M_DEVBUF);
@@ -218,7 +275,7 @@ atapibusattach(parent, self, aux)
}
}
-static void
+static __inline void
bswap (buf, len)
char *buf;
int len;
@@ -226,10 +283,10 @@ bswap (buf, len)
u_int16_t *p = (u_int16_t *)(buf + len);
while (--p >= (u_int16_t *)buf)
- *p = ntohs(*p);
-}
+ *p = (*p & 0xff) << 8 | (*p >> 8 & 0xff);
+}
-static void
+static __inline void
btrim (buf, len)
char *buf;
int len;
@@ -327,7 +384,7 @@ atapi_exec_io(ad_link, cmd, cmd_size, bp, flags)
pkt->bp = bp;
pkt->databuf = bp->b_data;
pkt->data_size = bp->b_bcount;
- pkt->flags = bp->b_flags & (B_READ|B_WRITE) | (flags & 0xff) |
+ pkt->flags = (bp->b_flags & (B_READ|B_WRITE)) | (flags & 0xff) |
(ad_link->flags & 0x0300);
pkt->drive = ad_link->drive;
diff --git a/sys/dev/atapi/atapilink.h b/sys/dev/atapi/atapilink.h
index f9a125276e8..cd9c2025680 100644
--- a/sys/dev/atapi/atapilink.h
+++ b/sys/dev/atapi/atapilink.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atapilink.h,v 1.4 1996/06/10 08:01:14 downsj Exp $ */
+/* $OpenBSD: atapilink.h,v 1.5 1996/08/07 01:56:29 downsj Exp $ */
/*
* Copyright (c) 1996 Manuel Bouyer. All rights reserved.
@@ -29,8 +29,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#undef ATAPI_DEBUG
-#undef ATAPI_DEBUG_PROBE
+/* #undef ATAPI_DEBUG */
+/* #undef ATAPI_DEBUG_PROBE */
struct bus_link {
u_int8_t type;
@@ -149,8 +149,11 @@ struct at_dev_link {
#define ACAP_DRQ_INTR 0x0100 /* interrupt DRQ */
#define ACAP_DRQ_ACCEL 0x0200 /* accelerated DRQ */
#define ACAP_LEN 0x0400 /* 16 bit commands */
- void (*start)(); /* device start routine */
- int (*done)(); /* device done routine */
+ u_int8_t quirks; /* per-device oddities */
+#define ADEV_CDROM 0x01 /* device is a CD-ROM */
+#define ADEV_LITTLETOC 0x02 /* Audio TOC uses wrong byte order */
+ void (*start) __P((void *)); /* device start routine */
+ int (*done) __P((void *)); /* device done routine */
};
struct atapi_command_packet {