diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1996-08-07 01:56:30 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1996-08-07 01:56:30 +0000 |
commit | 8f2506ae6e53c6e60bb719e41e203a97a5a5a9bd (patch) | |
tree | ca0a86713deb7a0bec6e305882164efa69cc551e /sys | |
parent | d5011bdf9d47ce16a5dd7f52ea0b46f5e60b3664 (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.c | 136 | ||||
-rw-r--r-- | sys/dev/atapi/atapiconf.c | 131 | ||||
-rw-r--r-- | sys/dev/atapi/atapilink.h | 13 |
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 { |