mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
Added driver to support ATAPI floppies ie LS-120 & ZIP drives.
Added "options ATA_STATIC_ID" that wires ATA disks like the old wd driver. Fixed problems: Dont use more sectors/intr than the drive supports. Fix announce of > 8.4G disks. Dont call ad_interrupt/ad_transfer when no disks config'd. Use the right page# for CDR write mode params. Fix breakage when no PCI support in kernel. Implement DEVFS stuff. General code clenaup.
This commit is contained in:
parent
90b4d77467
commit
b9bb98b32b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=44454
@ -25,12 +25,14 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ata-all.c,v 1.4 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: ata-all.c,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
#if NATA > 0
|
||||
#include "isa.h"
|
||||
#include "pci.h"
|
||||
#include "atadisk.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
@ -53,24 +55,28 @@
|
||||
#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */
|
||||
|
||||
/* prototypes */
|
||||
void ataintr(int32_t);
|
||||
#if NISA > 0
|
||||
static int32_t ata_isaprobe(struct isa_device *);
|
||||
static int32_t ata_isaattach(struct isa_device *);
|
||||
#endif
|
||||
#if NPCI > 0
|
||||
static const char *ata_pciprobe(pcici_t, pcidi_t);
|
||||
static void ata_pciattach(pcici_t, int32_t);
|
||||
static void promise_intr(int32_t);
|
||||
#endif
|
||||
static int32_t ata_probe(int32_t, int32_t, int32_t *);
|
||||
static int32_t ata_attach(int32_t);
|
||||
static void promise_intr(int32_t);
|
||||
static int32_t ata_reset(struct ata_softc *);
|
||||
static void ataintr(int32_t);
|
||||
static int32_t ata_device_attach(struct ata_softc *, int32_t);
|
||||
static int32_t atapi_device_attach(struct ata_softc *, int32_t);
|
||||
static void bswap(int8_t *, int32_t);
|
||||
static void btrim(int8_t *, int32_t);
|
||||
|
||||
static int32_t atanlun, sysctrl = 0;
|
||||
static int32_t atanlun = 0, sysctrl = 0;
|
||||
struct ata_softc *atadevices[MAXATA];
|
||||
struct isa_driver atadriver = { ata_isaprobe, ata_isaattach, "ata" };
|
||||
|
||||
#if NISA > 0
|
||||
static int32_t
|
||||
ata_isaprobe(struct isa_device *devp)
|
||||
{
|
||||
@ -85,7 +91,7 @@ ata_isaprobe(struct isa_device *devp)
|
||||
}
|
||||
res=ata_probe(devp->id_iobase, devp->id_iobase+ATA_ALTPORT, &devp->id_unit);
|
||||
if (res)
|
||||
devp->id_intr = ataintr;
|
||||
devp->id_intr = (inthand2_t *)ataintr;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -94,7 +100,9 @@ ata_isaattach(struct isa_device *devp)
|
||||
{
|
||||
return ata_attach(devp->id_unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NPCI > 0
|
||||
static u_long ata_pcicount;
|
||||
static struct pci_device ata_pcidevice = {
|
||||
"ata-pci", ata_pciprobe, ata_pciattach, &ata_pcicount, 0
|
||||
@ -127,7 +135,7 @@ ata_pciprobe(pcici_t tag, pcidi_t type)
|
||||
case 0x522910b9:
|
||||
return "Acer Aladdin IV/V IDE controller";
|
||||
default:
|
||||
return ("Unknown PCI IDE controller");
|
||||
return "Unknown PCI IDE controller";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -208,9 +216,10 @@ ata_pciattach(pcici_t tag, int32_t unit)
|
||||
register_intr(irq1, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun);
|
||||
else {
|
||||
if (sysctrl)
|
||||
pci_map_int(tag, promise_intr, (void *)lun, &bio_imask);
|
||||
pci_map_int(tag, (inthand2_t *)promise_intr,
|
||||
(void *)lun, &bio_imask);
|
||||
else
|
||||
pci_map_int(tag, ataintr, (void *)lun, &bio_imask);
|
||||
pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
|
||||
}
|
||||
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
|
||||
lun, iobase_1, irq1, unit);
|
||||
@ -221,7 +230,7 @@ ata_pciattach(pcici_t tag, int32_t unit)
|
||||
register_intr(irq2, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun);
|
||||
else {
|
||||
if (!sysctrl)
|
||||
pci_map_int(tag, ataintr, (void *) lun, &bio_imask);
|
||||
pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask);
|
||||
}
|
||||
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
|
||||
lun, iobase_2, irq2, unit);
|
||||
@ -237,37 +246,42 @@ promise_intr(int32_t unit)
|
||||
if (inl(sysctrl) & 0x00004000)
|
||||
ataintr(unit+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t
|
||||
ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
|
||||
{
|
||||
struct ata_softc *scp = atadevices[atanlun];
|
||||
u_int8_t status0, status1;
|
||||
int32_t mask = 0;
|
||||
int32_t timeout;
|
||||
int32_t lun = atanlun;
|
||||
u_int8_t status0, status1;
|
||||
|
||||
if (atanlun > MAXATA) {
|
||||
printf("ata: unit of of range(%d)\n", atanlun);
|
||||
return(0);
|
||||
#ifdef ATA_STATIC_ID
|
||||
atanlun++;
|
||||
#endif
|
||||
if (lun > MAXATA) {
|
||||
printf("ata: unit of of range(%d)\n", lun);
|
||||
return 0;
|
||||
}
|
||||
if (scp) {
|
||||
printf("ata%d: unit already attached\n", atanlun);
|
||||
return(0);
|
||||
printf("ata%d: unit already attached\n", lun);
|
||||
return 0;
|
||||
}
|
||||
scp = malloc(sizeof(struct ata_softc), M_DEVBUF, M_NOWAIT);
|
||||
if (scp == NULL) {
|
||||
printf("ata%d: failed to allocate driver storage\n", atanlun);
|
||||
return(0);
|
||||
printf("ata%d: failed to allocate driver storage\n", lun);
|
||||
return 0;
|
||||
}
|
||||
bzero(scp, sizeof(struct ata_softc));
|
||||
|
||||
scp->unit = atanlun;
|
||||
scp->unit = lun;
|
||||
scp->ioaddr = ioaddr;
|
||||
scp->altioaddr = altioaddr;
|
||||
|
||||
#ifdef ATA_DEBUG
|
||||
printf("ata%d: iobase=0x%04x altiobase=0x%04x\n",
|
||||
atanlun, scp->ioaddr, scp->altioaddr);
|
||||
scp->unit, scp->ioaddr, scp->altioaddr);
|
||||
#endif
|
||||
|
||||
/* do we have any signs of ATA/ATAPI HW being present ? */
|
||||
@ -283,7 +297,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
|
||||
mask |= 0x02;
|
||||
#ifdef ATA_DEBUG
|
||||
printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
|
||||
atanlun, mask, status0, status1);
|
||||
scp->unit, mask, status0, status1);
|
||||
#endif
|
||||
if (!mask) {
|
||||
free(scp, M_DEVBUF);
|
||||
@ -325,7 +339,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
|
||||
mask &= ~0x02;
|
||||
#ifdef ATA_DEBUG
|
||||
printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
|
||||
atanlun, mask, status0, status1);
|
||||
scp->unit, mask, status0, status1);
|
||||
#endif
|
||||
if (!mask) {
|
||||
free(scp, M_DEVBUF);
|
||||
@ -370,7 +384,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
|
||||
}
|
||||
}
|
||||
#ifdef ATA_DEBUG
|
||||
printf("ata%d: devices = 0x%x\n", atanlun, scp->devices);
|
||||
printf("ata%d: devices = 0x%x\n", scp->unit, scp->devices);
|
||||
#endif
|
||||
if (!(scp->devices & (ATA_ATA_MASTER|ATA_ATAPI_MASTER)))
|
||||
scp->flags |= ATA_F_SLAVE_ONLY;
|
||||
@ -380,8 +394,11 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
|
||||
}
|
||||
bufq_init(&scp->ata_queue);
|
||||
TAILQ_INIT(&scp->atapi_queue);
|
||||
*unit = atanlun;
|
||||
atadevices[atanlun++] = scp;
|
||||
*unit = scp->unit;
|
||||
atadevices[scp->unit] = scp;
|
||||
#ifndef ATA_STATIC_ID
|
||||
atanlun++;
|
||||
#endif
|
||||
return ATA_IOSIZE;
|
||||
}
|
||||
|
||||
@ -410,7 +427,7 @@ ata_attach(int32_t unit)
|
||||
return scp->devices;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ataintr(int32_t unit)
|
||||
{
|
||||
struct ata_softc *scp;
|
||||
@ -431,16 +448,12 @@ ataintr(int32_t unit)
|
||||
|
||||
/* find & call the responsible driver to process this interrupt */
|
||||
switch (scp->active) {
|
||||
case ATA_IDLE:
|
||||
if (intcount++ < 5)
|
||||
printf("ata%d: unwanted interrupt\n", unit);
|
||||
break;
|
||||
|
||||
#if NATADISK > 0
|
||||
case ATA_ACTIVE_ATA:
|
||||
if ((ata_request = bufq_first(&scp->ata_queue)))
|
||||
ad_interrupt(ata_request);
|
||||
break;
|
||||
|
||||
#endif
|
||||
case ATA_ACTIVE_ATAPI:
|
||||
if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue)))
|
||||
atapi_interrupt(atapi_request);
|
||||
@ -449,6 +462,12 @@ ataintr(int32_t unit)
|
||||
case ATA_IGNORE_INTR:
|
||||
scp->active = ATA_IDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
case ATA_IDLE:
|
||||
if (intcount++ < 5)
|
||||
printf("ata%d: unwanted interrupt\n", unit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,22 +527,6 @@ ata_wait(struct ata_softc *scp, u_int8_t mask)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ata_reset(struct ata_softc *scp)
|
||||
{
|
||||
outb(scp->altioaddr, ATA_A_RESET | ATA_A_IDS);
|
||||
DELAY(10000);
|
||||
outb(scp->altioaddr, ATA_A_IDS);
|
||||
DELAY(10000);
|
||||
inb(scp->ioaddr + ATA_ERROR);
|
||||
outb(scp->altioaddr, ATA_A_4BIT);
|
||||
if (ata_wait(scp, 0) < 0) {
|
||||
printf("ata%d: RESET failed\n", scp->unit);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ata_device_attach(struct ata_softc *scp, int32_t device)
|
||||
{
|
||||
|
@ -25,11 +25,10 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ata-all.h,v 1.3 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: ata-all.h,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
/* ATA register defines */
|
||||
|
||||
#define ATA_DATA 0x00 /* data register */
|
||||
#define ATA_ERROR 0x01 /* (R) error register */
|
||||
#define ATA_PRECOMP 0x01 /* (W) precompensation */
|
||||
@ -153,9 +152,7 @@ struct ata_params {
|
||||
int16_t securelevel;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing an ATA device
|
||||
*/
|
||||
/* Structure describing an ATA device */
|
||||
struct ata_softc {
|
||||
u_int32_t unit; /* this instance's number */
|
||||
u_int32_t ioaddr; /* port addr */
|
||||
@ -178,10 +175,6 @@ struct ata_softc {
|
||||
struct ata_params *ata_parm[2]; /* ata device params */
|
||||
TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */
|
||||
struct atapi_params *atapi_parm[2]; /* atapi device params */
|
||||
|
||||
#ifdef DEVFS
|
||||
static void *devfs_token;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ata_request {
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ata-disk.c,v 1.14 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: ata-disk.c,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -58,8 +58,8 @@
|
||||
|
||||
static d_open_t adopen;
|
||||
static d_close_t adclose;
|
||||
static d_write_t adwrite;
|
||||
static d_read_t adread;
|
||||
static d_write_t adwrite;
|
||||
static d_ioctl_t adioctl;
|
||||
static d_strategy_t adstrategy;
|
||||
static d_psize_t adpsize;
|
||||
@ -95,7 +95,7 @@ static void
|
||||
ad_attach(void *notused)
|
||||
{
|
||||
struct ad_softc *adp;
|
||||
int32_t ctlr, dev;
|
||||
int32_t ctlr, dev, secsperint;
|
||||
int8_t model_buf[40+1];
|
||||
int8_t revision_buf[8+1];
|
||||
|
||||
@ -103,6 +103,9 @@ ad_attach(void *notused)
|
||||
for (ctlr=0; ctlr<MAXATA && atadevices[ctlr]; ctlr++) {
|
||||
for (dev=0; dev<2; dev++) {
|
||||
if (atadevices[ctlr]->ata_parm[dev]) {
|
||||
#ifdef ATA_STATIC_ID
|
||||
adnlun = dev + ctlr * 2;
|
||||
#endif
|
||||
adp = adtab[adnlun];
|
||||
if (adp)
|
||||
printf("ad%d: unit already attached\n", adnlun);
|
||||
@ -113,20 +116,23 @@ ad_attach(void *notused)
|
||||
adp->controller = atadevices[ctlr];
|
||||
adp->ata_parm = atadevices[ctlr]->ata_parm[dev];
|
||||
adp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE;
|
||||
adp->lun = adnlun;
|
||||
adp->cylinders = adp->ata_parm->cylinders;
|
||||
adp->heads = adp->ata_parm->heads;
|
||||
adp->sectors = adp->ata_parm->sectors;
|
||||
adp->total_secs = adp->ata_parm->lbasize;
|
||||
if (!adp->total_secs)
|
||||
adp->total_secs = adp->cylinders*adp->heads*adp->sectors;
|
||||
if (adp->cylinders == 16383)
|
||||
adp->cylinders = adp->total_secs/(adp->heads*adp->sectors);
|
||||
|
||||
/* support multiple sectors / interrupt ? */
|
||||
if (ad_command(adp, ATA_C_SET_MULTI, 0, 0, 0, 16))
|
||||
adp->transfersize = DEV_BSIZE;
|
||||
else {
|
||||
if (ata_wait(adp->controller, ATA_S_DRDY) < 0)
|
||||
adp->transfersize = DEV_BSIZE;
|
||||
else
|
||||
adp->transfersize = 16*DEV_BSIZE;
|
||||
}
|
||||
adp->transfersize = DEV_BSIZE;
|
||||
secsperint = min(adp->ata_parm->nsecperint, 16);
|
||||
if (!ad_command(adp, ATA_C_SET_MULTI, 0, 0, 0, secsperint) &&
|
||||
ata_wait(adp->controller, ATA_S_DRDY) >= 0)
|
||||
adp->transfersize *= secsperint;
|
||||
|
||||
bpack(adp->ata_parm->model, model_buf, sizeof(model_buf));
|
||||
bpack(adp->ata_parm->revision, revision_buf,
|
||||
sizeof(revision_buf));
|
||||
@ -152,6 +158,18 @@ ad_attach(void *notused)
|
||||
DEVSTAT_NO_ORDERED_TAGS,
|
||||
DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE,
|
||||
0x180);
|
||||
#ifdef DEVFS
|
||||
adp->cdevs_token = devfs_add_devswf(&ad_cdevsw,
|
||||
dkmakeminor(adp->lun, 0, 0),
|
||||
DV_CHR,
|
||||
UID_ROOT, GID_OPERATOR,
|
||||
0640, "rad%d", adp->lun);
|
||||
adp->bdevs_token = devfs_add_devswf(&ad_cdevsw,
|
||||
dkmakeminor(adp->lun, 0, 0),
|
||||
DV_BLK,
|
||||
UID_ROOT, GID_OPERATOR,
|
||||
0640, "ad%d", adp->lun);
|
||||
#endif
|
||||
bufq_init(&adp->queue);
|
||||
adtab[adnlun++] = adp;
|
||||
}
|
||||
@ -245,17 +263,6 @@ adioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flags, struct proc *p)
|
||||
return ENOTTY;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
adpsize(dev_t dev)
|
||||
{
|
||||
struct ad_softc *adp;
|
||||
int32_t lun = UNIT(dev);
|
||||
|
||||
if (lun >= adnlun || !(adp = adtab[lun]))
|
||||
return -1;
|
||||
return (dssize(dev, &adp->slices, adopen, adclose));
|
||||
}
|
||||
|
||||
static void
|
||||
adstrategy(struct buf *bp)
|
||||
{
|
||||
@ -301,6 +308,17 @@ printf("adstrategy: entered\n");
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
adpsize(dev_t dev)
|
||||
{
|
||||
struct ad_softc *adp;
|
||||
int32_t lun = UNIT(dev);
|
||||
|
||||
if (lun >= adnlun || !(adp = adtab[lun]))
|
||||
return -1;
|
||||
return dssize(dev, &adp->slices, adopen, adclose);
|
||||
}
|
||||
|
||||
static void
|
||||
ad_strategy(struct buf *bp)
|
||||
{
|
||||
@ -434,14 +452,14 @@ ad_interrupt(struct buf *bp)
|
||||
if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR)) {
|
||||
oops:
|
||||
printf("ad%d: status=%02x error=%02x\n",
|
||||
adp->unit, adp->controller->status, adp->controller->error);
|
||||
adp->lun, adp->controller->status, adp->controller->error);
|
||||
if (adp->controller->status & ATA_S_ERROR) {
|
||||
printf("ad_interrupt: hard error");
|
||||
printf("ad_interrupt: hard error\n");
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
if (adp->controller->status & ATA_S_CORR)
|
||||
printf("ad_interrupt: soft ECC");
|
||||
printf("ad_interrupt: soft ECC\n");
|
||||
}
|
||||
/* if this was a read operation, get the data */
|
||||
if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ) && adp->active) {
|
||||
|
@ -25,17 +25,16 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ata-disk.h,v 1.5 1999/03/01 12:11:01 sos Exp $
|
||||
* $Id: ata-disk.h,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure describing an ATA disk
|
||||
*/
|
||||
/* Structure describing an ATA disk */
|
||||
struct ad_softc {
|
||||
struct ata_softc *controller; /* ptr to parent ctrl */
|
||||
struct ata_params *ata_parm; /* ata device params */
|
||||
struct diskslices *slices;
|
||||
int32_t unit; /* ATA_MASTER or ATA_SLAVE */
|
||||
int32_t lun; /* logical unit number */
|
||||
u_int16_t cylinders; /* disk geometry (probed) */
|
||||
u_int8_t heads;
|
||||
u_int8_t sectors;
|
||||
@ -47,9 +46,12 @@ struct ad_softc {
|
||||
u_int32_t donecount; /* bytes transferred */
|
||||
u_int32_t active; /* active processing request */
|
||||
u_int32_t flags; /* drive flags */
|
||||
#define AD_F_LABELLING 0x0001
|
||||
|
||||
struct devstat stats; /* devstat entry */
|
||||
#define AD_F_LABELLING 0x0001
|
||||
#ifdef DEVFS
|
||||
void *cdevs_token;
|
||||
void *bdevs_token;
|
||||
#endif
|
||||
};
|
||||
|
||||
void ad_transfer(struct buf *);
|
||||
|
@ -25,13 +25,13 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-all.c,v 1.5 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: atapi-all.c,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
#include "atapicd.h"
|
||||
#include "atapist.h"
|
||||
/*#include "atapifd.h"*/
|
||||
#include "atapifd.h"
|
||||
#include "opt_devfs.h"
|
||||
|
||||
#if NATA > 0
|
||||
@ -326,7 +326,7 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason);
|
||||
|
||||
TAILQ_REMOVE(&atp->controller->atapi_queue, request, chain);
|
||||
#ifdef ATAPI_DEBUG
|
||||
printf("atapi_interrupt: error=%02x\n", request->result);
|
||||
printf("atapi_interrupt: error=0x%02x\n", request->result);
|
||||
#endif
|
||||
if (request->callback) {
|
||||
(request->callback)(request);
|
||||
@ -341,7 +341,7 @@ printf("atapi_interrupt: error=%02x\n", request->result);
|
||||
void
|
||||
atapi_error(struct atapi_softc *atp, int32_t error)
|
||||
{
|
||||
printf("atapi: error = %02x\n", error);
|
||||
printf("atapi: error = 0x%02x\n", error);
|
||||
}
|
||||
|
||||
void
|
||||
@ -350,7 +350,7 @@ atapi_dump(int8_t *label, void *data, int32_t len)
|
||||
u_int8_t *p = data;
|
||||
|
||||
printf ("atapi: %s %x", label, *p++);
|
||||
while (--len > 0) printf ("-%x", *p++);
|
||||
while (--len > 0) printf ("-%02x", *p++);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-all.h,v 1.2 1999/03/01 12:11:01 sos Exp $
|
||||
* $Id: atapi-all.h,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
/* ATAPI misc defines */
|
||||
@ -88,25 +88,25 @@
|
||||
|
||||
/* ATAPI device parameter information */
|
||||
struct atapi_params {
|
||||
u_int cmdsize :2; /* packet command size */
|
||||
u_int8_t cmdsize :2; /* packet command size */
|
||||
#define ATAPI_PSIZE_12 0 /* 12 bytes */
|
||||
#define ATAPI_PSIZE_16 1 /* 16 bytes */
|
||||
|
||||
u_int :3;
|
||||
u_int drqtype :2; /* DRQ type */
|
||||
u_int8_t :3;
|
||||
u_int8_t drqtype :2; /* DRQ type */
|
||||
#define ATAPI_DRQT_MPROC 0 /* cpu 3 ms delay */
|
||||
#define ATAPI_DRQT_INTR 1 /* intr 10 ms delay */
|
||||
#define ATAPI_DRQT_ACCEL 2 /* accel 50 us delay */
|
||||
|
||||
u_int removable :1; /* device is removable */
|
||||
u_int device_type :5; /* device type */
|
||||
u_int8_t removable :1; /* device is removable */
|
||||
u_int8_t device_type :5; /* device type */
|
||||
#define ATAPI_TYPE_DIRECT 0 /* disk/floppy */
|
||||
#define ATAPI_TYPE_TAPE 1 /* streaming tape */
|
||||
#define ATAPI_TYPE_CDROM 5 /* CD-ROM device */
|
||||
#define ATAPI_TYPE_OPTICAL 7 /* optical disk */
|
||||
|
||||
u_int :1;
|
||||
u_int proto :2; /* command protocol */
|
||||
u_int8_t :1;
|
||||
u_int8_t proto :2; /* command protocol */
|
||||
#define ATAPI_PROTO_ATAPI 2
|
||||
|
||||
int16_t reserved1[9];
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-cd.c,v 1.5 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: atapi-cd.c,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -56,8 +56,8 @@
|
||||
|
||||
static d_open_t acdopen;
|
||||
static d_close_t acdclose;
|
||||
static d_write_t acdwrite;
|
||||
static d_read_t acdread;
|
||||
static d_write_t acdwrite;
|
||||
static d_ioctl_t acdioctl;
|
||||
static d_strategy_t acdstrategy;
|
||||
|
||||
@ -106,6 +106,9 @@ static int32_t acd_close_track(struct acd_softc *);
|
||||
static int32_t acd_close_disk(struct acd_softc *);
|
||||
static int32_t acd_read_track_info(struct acd_softc *, int, struct acd_track_info*);
|
||||
static int32_t acd_blank_disk(struct acd_softc *);
|
||||
static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
|
||||
static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
|
||||
static void acd_drvinit(void *);
|
||||
|
||||
int
|
||||
acdattach(struct atapi_softc *atp)
|
||||
@ -201,7 +204,7 @@ acdattach(struct atapi_softc *atp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acd_softc *
|
||||
static struct acd_softc *
|
||||
acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats)
|
||||
{
|
||||
struct acd_softc *acd;
|
||||
@ -227,27 +230,25 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats)
|
||||
else
|
||||
acd->stats = stats;
|
||||
#ifdef DEVFS
|
||||
acd->ra_devfs_token =
|
||||
devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR, 0640,
|
||||
"racd%da", lun);
|
||||
acd->rc_devfs_token =
|
||||
devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR, 0640,
|
||||
"racd%dc", lun);
|
||||
acd->a_devfs_token =
|
||||
devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
|
||||
DV_BLK, UID_ROOT, GID_OPERATOR, 0640,
|
||||
"acd%da", lun);
|
||||
acd->c_devfs_token =
|
||||
devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
|
||||
DV_BLK, UID_ROOT, GID_OPERATOR, 0640,
|
||||
"acd%dc", lun);
|
||||
acd->a_cdevfs_token = devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR, 0644,
|
||||
"racd%da", lun);
|
||||
acd->c_cdevfs_token = devfs_add_devswf(&acd_cdevsw,
|
||||
dkmakeminor(lun, 0, RAW_PART),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR, 0644,
|
||||
"racd%dc", lun);
|
||||
acd->a_bdevfs_token = devfs_add_devswf(&acd_cdevsw, dkmakeminor(lun, 0, 0),
|
||||
DV_BLK, UID_ROOT, GID_OPERATOR, 0644,
|
||||
"acd%da", lun);
|
||||
acd->c_bdevfs_token = devfs_add_devswf(&acd_cdevsw,
|
||||
dkmakeminor(lun, 0, RAW_PART),
|
||||
DV_BLK, UID_ROOT, GID_OPERATOR, 0644,
|
||||
"acd%dc", lun);
|
||||
#endif
|
||||
return acd;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
acd_describe(struct acd_softc *cdp)
|
||||
{
|
||||
int32_t comma;
|
||||
@ -377,7 +378,24 @@ acd_describe(struct acd_softc *cdp)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int
|
||||
static __inline void
|
||||
lba2msf(int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
|
||||
{
|
||||
lba += 150;
|
||||
lba &= 0xffffff;
|
||||
*m = lba / (60 * 75);
|
||||
lba %= (60 * 75);
|
||||
*s = lba / 75;
|
||||
*f = lba % 75;
|
||||
}
|
||||
|
||||
static __inline int32_t
|
||||
msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
|
||||
{
|
||||
return (m * 60 + s) * 75 + f - 150;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
int32_t lun = dkunit(dev);
|
||||
@ -393,7 +411,7 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
if (fmt == S_IFBLK)
|
||||
cdp->flags |= F_BOPEN;
|
||||
else
|
||||
++cdp->refcnt;
|
||||
cdp->refcnt++;
|
||||
|
||||
if ((flags & O_NONBLOCK) == 0) {
|
||||
if ((flags & FWRITE) != 0) {
|
||||
@ -413,7 +431,7 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
static int32_t
|
||||
acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
int32_t lun = dkunit(dev);
|
||||
@ -425,7 +443,7 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
if (fmt == S_IFBLK)
|
||||
cdp->flags &= ~F_BOPEN;
|
||||
else
|
||||
--cdp->refcnt;
|
||||
cdp->refcnt--;
|
||||
|
||||
/* Are we the last open ?? */
|
||||
if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
|
||||
@ -442,155 +460,19 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acdread(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return physio(acdstrategy, NULL, dev, 1, minphys, uio);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acdwrite(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return physio(acdstrategy, NULL, dev, 0, minphys, uio);
|
||||
}
|
||||
|
||||
void
|
||||
acdstrategy(struct buf *bp)
|
||||
{
|
||||
int32_t lun = dkunit(bp->b_dev);
|
||||
struct acd_softc *cdp = acdtab[lun];
|
||||
int32_t x;
|
||||
|
||||
#ifdef NOTYET
|
||||
/* allow write only on CD-R/RW media */ /* all for now SOS */
|
||||
if (!(bp->b_flags & B_READ) && !(writeable_media)) {
|
||||
bp->b_error = EROFS;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bp->b_bcount == 0) {
|
||||
bp->b_resid = 0;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for valid blocksize SOS */
|
||||
|
||||
bp->b_pblkno = bp->b_blkno;
|
||||
bp->b_resid = bp->b_bcount;
|
||||
|
||||
x = splbio();
|
||||
bufqdisksort(&cdp->buf_queue, bp);
|
||||
acd_start(cdp);
|
||||
splx(x);
|
||||
}
|
||||
|
||||
static void
|
||||
acd_start(struct acd_softc *cdp)
|
||||
{
|
||||
struct buf *bp = bufq_first(&cdp->buf_queue);
|
||||
u_long lba, count;
|
||||
int8_t ccb[16];
|
||||
|
||||
if (!bp)
|
||||
return;
|
||||
bzero(ccb, sizeof(ccb));
|
||||
bufq_remove(&cdp->buf_queue, bp);
|
||||
|
||||
/* Should reject all queued entries if media have changed. */
|
||||
if (cdp->flags & F_MEDIA_CHANGED) {
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
acd_select_slot(cdp);
|
||||
if ((bp->b_flags & B_READ) == B_WRITE) {
|
||||
if ((cdp->flags & F_TRACK_PREPED) == 0) {
|
||||
if ((cdp->flags & F_TRACK_PREP) == 0) {
|
||||
printf("acd%d: sequence error\n", cdp->lun);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
} else {
|
||||
if (acd_open_track(cdp, &cdp->preptrack) != 0) {
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
cdp->flags |= F_TRACK_PREPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bp->b_flags & B_READ) {
|
||||
lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
|
||||
ccb[0] = ATAPI_READ_BIG;
|
||||
}
|
||||
else {
|
||||
lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size);
|
||||
ccb[0] = ATAPI_WRITE_BIG;
|
||||
}
|
||||
count = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
|
||||
|
||||
ccb[1] = 0;
|
||||
ccb[2] = lba>>24;
|
||||
ccb[3] = lba>>16;
|
||||
ccb[4] = lba>>8;
|
||||
ccb[5] = lba;
|
||||
ccb[7] = count>>8;
|
||||
ccb[8] = count;
|
||||
|
||||
devstat_start_transaction(cdp->stats);
|
||||
|
||||
atapi_queue_cmd(cdp->atp, ccb, bp->b_data, bp->b_bcount,
|
||||
(bp->b_flags&B_READ)?A_READ : 0, acd_done, cdp, (void *)bp);
|
||||
}
|
||||
|
||||
static void
|
||||
acd_done(struct atapi_request *request)
|
||||
{
|
||||
struct buf *bp = request->bp;
|
||||
struct acd_softc *cdp = request->driver;
|
||||
|
||||
devstat_end_transaction(cdp->stats, bp->b_bcount-request->bytecount,
|
||||
DEVSTAT_TAG_NONE,
|
||||
(bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE);
|
||||
if (request->result) {
|
||||
printf("acd_done: ");
|
||||
atapi_error(request->device, request->result);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
else {
|
||||
bp->b_resid = request->bytecount;
|
||||
if ((bp->b_flags & B_READ) == B_WRITE)
|
||||
cdp->flags |= F_WRITTEN;
|
||||
}
|
||||
biodone(bp);
|
||||
acd_start(cdp);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
lba2msf(int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f)
|
||||
{
|
||||
lba += 150;
|
||||
lba &= 0xffffff;
|
||||
*m = lba / (60 * 75);
|
||||
lba %= (60 * 75);
|
||||
*s = lba / 75;
|
||||
*f = lba % 75;
|
||||
}
|
||||
|
||||
static __inline int32_t
|
||||
msf2lba(u_int8_t m, u_int8_t s, u_int8_t f)
|
||||
{
|
||||
return (m * 60 + s) * 75 + f - 150;
|
||||
}
|
||||
|
||||
int32_t
|
||||
static int32_t
|
||||
acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
{
|
||||
int32_t lun = dkunit(dev);
|
||||
@ -634,7 +516,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
case CDIOCRESET:
|
||||
error = suser(p->p_ucred, &p->p_acflag);
|
||||
if (error)
|
||||
return (error);
|
||||
return error;
|
||||
return acd_test_unit_ready(cdp);
|
||||
|
||||
case CDIOCEJECT:
|
||||
@ -658,7 +540,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)addr;
|
||||
struct toc *toc = &cdp->toc;
|
||||
struct toc buf;
|
||||
u_long len;
|
||||
u_int32_t len;
|
||||
u_int8_t starting_track = te->starting_track;
|
||||
|
||||
if (!cdp->toc.hdr.ending_track)
|
||||
@ -741,7 +623,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
struct ioc_read_subchannel *args =
|
||||
(struct ioc_read_subchannel *)addr;
|
||||
struct cd_sub_channel_info data;
|
||||
u_long len = args->data_len;
|
||||
u_int32_t len = args->data_len;
|
||||
int32_t abslba, rellba;
|
||||
int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0,
|
||||
sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
|
||||
@ -755,7 +637,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
sizeof(cdp->subchan), A_READ, NULL, NULL, NULL))
|
||||
return EIO;
|
||||
#ifdef ACD_DEBUG
|
||||
atapi_dump("acd: subchan", &cdp->subchan, sizeof(cdp->subchan));
|
||||
atapi_dump("acd: subchan", &cdp->subchan, sizeof(cdp->subchan));
|
||||
#endif
|
||||
|
||||
abslba = cdp->subchan.abslba;
|
||||
@ -807,7 +689,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
case CDIOCPLAYTRACKS:
|
||||
{
|
||||
struct ioc_play_track *args = (struct ioc_play_track *)addr;
|
||||
u_long start, len;
|
||||
u_int32_t start, len;
|
||||
int32_t t1, t2;
|
||||
int8_t ccb[16];
|
||||
|
||||
@ -1049,6 +931,128 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
acdstrategy(struct buf *bp)
|
||||
{
|
||||
int32_t lun = dkunit(bp->b_dev);
|
||||
struct acd_softc *cdp = acdtab[lun];
|
||||
int32_t x;
|
||||
|
||||
#ifdef NOTYET
|
||||
/* allow write only on CD-R/RW media */ /* all for now SOS */
|
||||
if (!(bp->b_flags & B_READ) && !(writeable_media)) {
|
||||
bp->b_error = EROFS;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bp->b_bcount == 0) {
|
||||
bp->b_resid = 0;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* check for valid blocksize SOS */
|
||||
|
||||
bp->b_pblkno = bp->b_blkno;
|
||||
bp->b_resid = bp->b_bcount;
|
||||
|
||||
x = splbio();
|
||||
bufqdisksort(&cdp->buf_queue, bp);
|
||||
acd_start(cdp);
|
||||
splx(x);
|
||||
}
|
||||
|
||||
static void
|
||||
acd_start(struct acd_softc *cdp)
|
||||
{
|
||||
struct buf *bp = bufq_first(&cdp->buf_queue);
|
||||
u_int32_t lba, count;
|
||||
int8_t ccb[16];
|
||||
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
bufq_remove(&cdp->buf_queue, bp);
|
||||
|
||||
/* Should reject all queued entries if media have changed. */
|
||||
if (cdp->flags & F_MEDIA_CHANGED) {
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
acd_select_slot(cdp);
|
||||
if ((bp->b_flags & B_READ) == B_WRITE) {
|
||||
if ((cdp->flags & F_TRACK_PREPED) == 0) {
|
||||
if ((cdp->flags & F_TRACK_PREP) == 0) {
|
||||
printf("acd%d: sequence error\n", cdp->lun);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
} else {
|
||||
if (acd_open_track(cdp, &cdp->preptrack) != 0) {
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
cdp->flags |= F_TRACK_PREPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
bzero(ccb, sizeof(ccb));
|
||||
if (bp->b_flags & B_READ) {
|
||||
lba = bp->b_blkno / (cdp->block_size / DEV_BSIZE);
|
||||
ccb[0] = ATAPI_READ_BIG;
|
||||
}
|
||||
else {
|
||||
lba = cdp->next_writeable_lba + (bp->b_offset / cdp->block_size);
|
||||
ccb[0] = ATAPI_WRITE_BIG;
|
||||
}
|
||||
count = (bp->b_bcount + (cdp->block_size - 1)) / cdp->block_size;
|
||||
|
||||
#ifdef ACD_DEBUG
|
||||
printf("acd%d: lba=%d, count=%d\n", cdp->lun, lba, count);
|
||||
#endif
|
||||
ccb[1] = 0;
|
||||
ccb[2] = lba>>24;
|
||||
ccb[3] = lba>>16;
|
||||
ccb[4] = lba>>8;
|
||||
ccb[5] = lba;
|
||||
ccb[7] = count>>8;
|
||||
ccb[8] = count;
|
||||
|
||||
devstat_start_transaction(cdp->stats);
|
||||
|
||||
atapi_queue_cmd(cdp->atp, ccb, bp->b_data, bp->b_bcount,
|
||||
(bp->b_flags&B_READ)?A_READ : 0, acd_done, cdp, (void *)bp);
|
||||
}
|
||||
|
||||
static void
|
||||
acd_done(struct atapi_request *request)
|
||||
{
|
||||
struct buf *bp = request->bp;
|
||||
struct acd_softc *cdp = request->driver;
|
||||
|
||||
devstat_end_transaction(cdp->stats, bp->b_bcount-request->bytecount,
|
||||
DEVSTAT_TAG_NONE,
|
||||
(bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE);
|
||||
if (request->result) {
|
||||
atapi_error(request->device, request->result);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
else {
|
||||
bp->b_resid = request->bytecount;
|
||||
if ((bp->b_flags & B_READ) == B_WRITE)
|
||||
cdp->flags |= F_WRITTEN;
|
||||
}
|
||||
biodone(bp);
|
||||
acd_start(cdp);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
acd_test_unit_ready(struct acd_softc *cdp)
|
||||
{
|
||||
@ -1095,8 +1099,8 @@ acd_mode_sense(struct acd_softc *cdp, u_int8_t page,
|
||||
|
||||
error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ,
|
||||
NULL, NULL, NULL);
|
||||
#ifdef AST_DEBUG
|
||||
atapi_dump("acd: mode sense ", &cdp->au, sizeof(cdp->au));
|
||||
#ifdef ACD_DEBUG
|
||||
atapi_dump("acd: mode sense ", pagebuf, pagesize);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
@ -1107,8 +1111,9 @@ acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize)
|
||||
int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, 0, 0, 0, 0,
|
||||
pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
#ifdef AST_DEBUG
|
||||
atapi_dump("acd: mode select ", &cdp->au, sizeof(cdp->au));
|
||||
#ifdef ACD_DEBUG
|
||||
printf("acd: modeselect pagesize=%d\n", pagesize);
|
||||
atapi_dump("acd: mode select ", pagebuf, pagesize);
|
||||
#endif
|
||||
return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0,
|
||||
NULL, NULL, NULL);
|
||||
@ -1196,9 +1201,6 @@ acd_read_toc(struct acd_softc *cdp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the audio channel masks.
|
||||
*/
|
||||
static int32_t
|
||||
acd_setchan(struct acd_softc *cdp,
|
||||
u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3)
|
||||
@ -1287,7 +1289,7 @@ acd_select_slot(struct acd_softc *cdp)
|
||||
acd_lock_device(cdp, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_rezero_unit(struct acd_softc *cdp)
|
||||
{
|
||||
int8_t ccb[16];
|
||||
@ -1297,14 +1299,14 @@ acd_rezero_unit(struct acd_softc *cdp)
|
||||
return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_open_disk(struct acd_softc *cdp, int32_t test)
|
||||
{
|
||||
cdp->next_writeable_lba = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_close_disk(struct acd_softc *cdp)
|
||||
{
|
||||
int8_t ccb[16];
|
||||
@ -1316,7 +1318,7 @@ acd_close_disk(struct acd_softc *cdp)
|
||||
return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp)
|
||||
{
|
||||
struct write_param param;
|
||||
@ -1386,7 +1388,7 @@ acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp)
|
||||
return acd_mode_select(cdp, ¶m, sizeof(param));
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_close_track(struct acd_softc *cdp)
|
||||
{
|
||||
int8_t ccb[16];
|
||||
@ -1396,7 +1398,7 @@ acd_close_track(struct acd_softc *cdp)
|
||||
return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_read_track_info(struct acd_softc *cdp,
|
||||
int32_t lba, struct acd_track_info *info)
|
||||
{
|
||||
@ -1418,7 +1420,7 @@ acd_read_track_info(struct acd_softc *cdp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
acd_blank_disk(struct acd_softc *cdp)
|
||||
{
|
||||
int32_t error;
|
||||
|
@ -25,21 +25,17 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-cd.h,v 1.3 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: atapi-cd.h,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* CDROM Table Of Contents
|
||||
*/
|
||||
/* CDROM Table Of Contents */
|
||||
#define MAXTRK 99
|
||||
struct toc {
|
||||
struct ioc_toc_header hdr;
|
||||
struct cd_toc_entry tab[MAXTRK + 1];
|
||||
struct ioc_toc_header hdr;
|
||||
struct cd_toc_entry tab[MAXTRK + 1];
|
||||
};
|
||||
|
||||
/*
|
||||
* CDROM Audio Control Parameters Page
|
||||
*/
|
||||
/* CDROM Audio Control Parameters Page */
|
||||
struct audiopage {
|
||||
/* Mode Page data header */
|
||||
u_int16_t data_length;
|
||||
@ -63,22 +59,21 @@ struct audiopage {
|
||||
u_int8_t reserved5;
|
||||
u_int16_t lb_per_sec;
|
||||
struct port_control {
|
||||
u_int8_t channels:4;
|
||||
u_int8_t channels:4;
|
||||
#define CHANNEL_0 1
|
||||
#define CHANNEL_1 2
|
||||
#define CHANNEL_2 4
|
||||
#define CHANNEL_3 8
|
||||
u_int8_t volume;
|
||||
|
||||
u_int8_t volume;
|
||||
} port[4];
|
||||
};
|
||||
|
||||
/*
|
||||
* CDROM Capabilities and Mechanical Status Page
|
||||
*/
|
||||
/* CDROM Capabilities and Mechanical Status Page */
|
||||
struct cappage {
|
||||
/* Mode data header */
|
||||
u_int16_t data_length;
|
||||
u_int8_t medium_type; /* Present media type */
|
||||
u_int8_t medium_type;
|
||||
#define MST_TYPE_MASK_LOW 0x0f
|
||||
#define MST_FMT_NONE 0x00
|
||||
#define MST_DATA_120 0x01
|
||||
@ -108,55 +103,55 @@ struct cappage {
|
||||
#define ATAPI_CDROM_CAP_PAGE 0x2a
|
||||
|
||||
u_int8_t param_len;
|
||||
u_int8_t read_cdr :1; /* Supports CD-R read */
|
||||
u_int8_t read_cdrw :1; /* Supports CD-RW read */
|
||||
u_int8_t method2 :1; /* Supports reading packet tracks */
|
||||
u_int8_t byte2_37 :5;
|
||||
u_int8_t write_cdr :1; /* Supports CD-R write */
|
||||
u_int8_t write_cdrw :1; /* Supports CD-RW write */
|
||||
u_int8_t test_write :1; /* Supports test writing */
|
||||
u_int8_t byte3_37 :5;
|
||||
u_int8_t audio_play :1; /* Audio play supported */
|
||||
u_int8_t composite :1; /* Composite audio/video supported */
|
||||
u_int8_t dport1 :1; /* Digital audio on port 1 */
|
||||
u_int8_t dport2 :1; /* Digital audio on port 2 */
|
||||
u_int8_t mode2_form1 :1; /* Mode 2 form 1 (XA) read */
|
||||
u_int8_t mode2_form2 :1; /* Mode 2 form 2 format */
|
||||
u_int8_t multisession :1; /* Multi-session photo-CD */
|
||||
u_int8_t read_cdr :1; /* supports CD-R read */
|
||||
u_int8_t read_cdrw :1; /* supports CD-RW read */
|
||||
u_int8_t method2 :1; /* supports reading packet tracks */
|
||||
u_int8_t reserved2_37 :5;
|
||||
u_int8_t write_cdr :1; /* supports CD-R write */
|
||||
u_int8_t write_cdrw :1; /* supports CD-RW write */
|
||||
u_int8_t test_write :1; /* supports test writing */
|
||||
u_int8_t reserved3_37 :5;
|
||||
u_int8_t audio_play :1; /* audio play supported */
|
||||
u_int8_t composite :1; /* composite audio/video supported */
|
||||
u_int8_t dport1 :1; /* digital audio on port 1 */
|
||||
u_int8_t dport2 :1; /* digital audio on port 2 */
|
||||
u_int8_t mode2_form1 :1; /* mode 2 form 1 (XA) read */
|
||||
u_int8_t mode2_form2 :1; /* mode 2 form 2 format */
|
||||
u_int8_t multisession :1; /* multi-session photo-CD */
|
||||
u_int8_t :1;
|
||||
u_int8_t cd_da :1; /* Audio-CD read supported */
|
||||
u_int8_t cd_da :1; /* audio-CD read supported */
|
||||
u_int8_t cd_da_stream :1; /* CD-DA streaming */
|
||||
u_int8_t rw :1; /* Combined R-W subchannels */
|
||||
u_int8_t rw :1; /* combined R-W subchannels */
|
||||
u_int8_t rw_corr :1; /* R-W subchannel data corrected */
|
||||
u_int8_t c2 :1; /* C2 error pointers supported */
|
||||
u_int8_t isrc :1; /* Can return the ISRC info */
|
||||
u_int8_t upc :1; /* Can return the catalog number UPC */
|
||||
u_int8_t isrc :1; /* can return the ISRC info */
|
||||
u_int8_t upc :1; /* can return the catalog number UPC */
|
||||
u_int8_t :1;
|
||||
u_int8_t lock :1; /* Can be locked */
|
||||
u_int8_t locked :1; /* Current lock state */
|
||||
u_int8_t prevent :1; /* Prevent jumper installed */
|
||||
u_int8_t eject :1; /* Can eject */
|
||||
u_int8_t lock :1; /* can be locked */
|
||||
u_int8_t locked :1; /* current lock state */
|
||||
u_int8_t prevent :1; /* prevent jumper installed */
|
||||
u_int8_t eject :1; /* can eject */
|
||||
u_int8_t :1;
|
||||
u_int8_t mech :3; /* Loading mechanism type */
|
||||
u_int8_t mech :3; /* loading mechanism type */
|
||||
#define MST_MECH_CADDY 0
|
||||
#define MST_MECH_TRAY 1
|
||||
#define MST_MECH_POPUP 2
|
||||
#define MST_MECH_CHANGER 4
|
||||
#define MST_MECH_CARTRIDGE 5
|
||||
|
||||
u_int8_t sep_vol :1; /* Independent volume of channels */
|
||||
u_int8_t sep_mute :1; /* Independent mute of channels */
|
||||
u_int8_t sep_vol :1; /* independent volume of channels */
|
||||
u_int8_t sep_mute :1; /* independent mute of channels */
|
||||
u_int8_t:6;
|
||||
|
||||
u_int16_t max_speed; /* Max raw data rate in bytes/1000 */
|
||||
u_int16_t max_vol_levels; /* Number of discrete volume levels */
|
||||
u_int16_t buf_size; /* Internal buffer size in bytes/1024 */
|
||||
u_int16_t cur_speed; /* Current data rate in bytes/1000 */
|
||||
u_int16_t max_speed; /* max raw data rate in bytes/1000 */
|
||||
u_int16_t max_vol_levels; /* number of discrete volume levels */
|
||||
u_int16_t buf_size; /* internal buffer size in bytes/1024 */
|
||||
u_int16_t cur_speed; /* current data rate in bytes/1000 */
|
||||
|
||||
u_int8_t reserved3;
|
||||
u_int8_t bckf :1; /* Data valid on failing edge of BCK */
|
||||
u_int8_t rch :1; /* High LRCK indicates left channel */
|
||||
u_int8_t lsbf :1; /* Set if LSB first */
|
||||
u_int8_t bckf :1; /* data valid on failing edge of BCK */
|
||||
u_int8_t rch :1; /* high LRCK indicates left channel */
|
||||
u_int8_t lsbf :1; /* set if LSB first */
|
||||
u_int8_t dlen :2;
|
||||
#define MST_DLEN_32 0
|
||||
#define MST_DLEN_16 1
|
||||
@ -167,42 +162,38 @@ struct cappage {
|
||||
u_int8_t reserved4[2];
|
||||
};
|
||||
|
||||
/*
|
||||
* CDROM Changer mechanism status structure
|
||||
*/
|
||||
/* CDROM Changer mechanism status structure */
|
||||
struct changer {
|
||||
u_int8_t current_slot :5; /* Active changer slot */
|
||||
u_int8_t mech_state :2; /* Current changer state */
|
||||
u_int8_t current_slot :5; /* active changer slot */
|
||||
u_int8_t mech_state :2; /* current changer state */
|
||||
#define CH_READY 0
|
||||
#define CH_LOADING 1
|
||||
#define CH_UNLOADING 2
|
||||
#define CH_INITIALIZING 3
|
||||
|
||||
u_int8_t fault :1; /* Fault in last operation */
|
||||
u_int8_t fault :1; /* fault in last operation */
|
||||
u_int8_t reserved0 :5;
|
||||
u_int8_t cd_state :3; /* Current mechanism state */
|
||||
u_int8_t cd_state :3; /* current mechanism state */
|
||||
#define CD_IDLE 0
|
||||
#define CD_AUDIO_ACTIVE 1
|
||||
#define CD_AUDIO_SCAN 2
|
||||
#define CD_HOST_ACTIVE 3
|
||||
#define CD_NO_STATE 7
|
||||
|
||||
u_int8_t current_lba[3]; /* Current LBA */
|
||||
u_int8_t slots; /* Number of available slots */
|
||||
u_int16_t table_length; /* Slot table length */
|
||||
u_int8_t current_lba[3]; /* current LBA */
|
||||
u_int8_t slots; /* number of available slots */
|
||||
u_int16_t table_length; /* slot table length */
|
||||
struct {
|
||||
u_int8_t changed :1; /* Media has changed in this slot */
|
||||
u_int8_t unused :6;
|
||||
u_int8_t present :1; /* Slot has a CD present */
|
||||
u_int8_t reserved0;
|
||||
u_int8_t reserved1;
|
||||
u_int8_t reserved2;
|
||||
u_int8_t changed :1; /* media has changed in this slot */
|
||||
u_int8_t unused :6;
|
||||
u_int8_t present :1; /* slot has a CD present */
|
||||
u_int8_t reserved0;
|
||||
u_int8_t reserved1;
|
||||
u_int8_t reserved2;
|
||||
} slot[32];
|
||||
};
|
||||
|
||||
/*
|
||||
* CDROM Write Parameters Mode Page (Burners ONLY)
|
||||
*/
|
||||
/* CDROM Write Parameters Mode Page (Burners ONLY) */
|
||||
struct write_param {
|
||||
/* Mode Page data header */
|
||||
u_int16_t data_length;
|
||||
@ -213,63 +204,63 @@ struct write_param {
|
||||
|
||||
/* Write Parameters mode page */
|
||||
u_int8_t page_code;
|
||||
#define ATAPI_CDROM_WRITE_PARAMETERS_PAGE 0x0e
|
||||
#define ATAPI_CDROM_WRITE_PARAMETERS_PAGE 0x05
|
||||
|
||||
u_int8_t page_length; /* 0x32 */
|
||||
u_int8_t write_type :4; /* Write stream type */
|
||||
u_int8_t write_type :4; /* write stream type */
|
||||
#define CDR_WTYPE_PACKET 0x00
|
||||
#define CDR_WTYPE_TRACK 0x01
|
||||
#define CDR_WTYPE_SESSION 0x02
|
||||
#define CDR_WTYPE_RAW 0x03
|
||||
|
||||
u_int8_t test_write :1; /* Test write enable */
|
||||
u_int8_t test_write :1; /* test write enable */
|
||||
u_int8_t reserved2_567 :3;
|
||||
u_int8_t track_mode :4; /* Track mode */
|
||||
u_int8_t track_mode :4; /* track mode */
|
||||
#define CDR_TMODE_AUDIO 0x01
|
||||
#define CDR_TMODE_INCR_DATA 0x01
|
||||
#define CDR_TMODE_ALLOW_COPY 0x02
|
||||
#define CDR_TMODE_DATA 0x04
|
||||
#define CDR_TMODE_QUAD_AUDIO 0x08
|
||||
|
||||
u_int8_t copy :1; /* Generation stamp */
|
||||
u_int8_t fp :1; /* Fixed packet type */
|
||||
u_int8_t multi_session :2; /* Multi-session type */
|
||||
u_int8_t copy :1; /* generation stamp */
|
||||
u_int8_t fp :1; /* fixed packet type */
|
||||
u_int8_t multi_session :2; /* multi-session type */
|
||||
#define CDR_MSES_NONE 0x00
|
||||
#define CDR_MSES_FINAL 0x01
|
||||
#define CDR_MSES_RESERVED 0x02
|
||||
#define CDR_MSES_NULTI 0x03
|
||||
|
||||
u_int8_t data_block_type :4; /* Data block type code */
|
||||
u_int8_t data_block_type :4; /* data block type code */
|
||||
#define CDR_DB_RAW 0x0 /* 2352 bytes of raw data */
|
||||
#define CDR_DB_RAW_PQ 0x1 /* 2368 bytes raw data + P/Q subchan */
|
||||
#define CDR_DB_RAW_PW 0x2 /* 2448 bytes raw data + P-W subchan */
|
||||
#define CDR_DB_RAW_PW_R 0x3 /* 2448 bytes raw data + P-W raw sub */
|
||||
#define CDR_DB_RES_4 0x4 /* Reserved */
|
||||
#define CDR_DB_RES_5 0x5 /* Reserved */
|
||||
#define CDR_DB_RES_6 0x6 /* Reserved */
|
||||
#define CDR_DB_VS_7 0x7 /* Vendor specific */
|
||||
#define CDR_DB_RES_4 0x4 /* reserved */
|
||||
#define CDR_DB_RES_5 0x5 /* reserved */
|
||||
#define CDR_DB_RES_6 0x6 /* reserved */
|
||||
#define CDR_DB_VS_7 0x7 /* vendor specific */
|
||||
#define CDR_DB_ROM_MODE1 0x8 /* 2048 bytes Mode 1 (ISO/IEC 10149) */
|
||||
#define CDR_DB_ROM_MODE2 0x9 /* 2336 bytes Mode 2 (ISO/IEC 10149) */
|
||||
#define CDR_DB_XA_MODE1 0x10 /* 2048 bytes Mode 1 (CD-ROM XA 1) */
|
||||
#define CDR_DB_XA_MODE2_F1 0x11 /* 2056 bytes Mode 2 (CD-ROM XA 1) */
|
||||
#define CDR_DB_XA_MODE2_F2 0x12 /* 2324 bytes Mode 2 (CD-ROM XA 2) */
|
||||
#define CDR_DB_XA_MODE2_MIX 0x13 /* 2332 bytes Mode 2 (CD-ROM XA 1/2) */
|
||||
#define CDR_DB_RES_14 0x14 /* Reserved */
|
||||
#define CDR_DB_VS_15 0x15 /* Vendor specific */
|
||||
#define CDR_DB_RES_14 0x14 /* reserved */
|
||||
#define CDR_DB_VS_15 0x15 /* vendor specific */
|
||||
|
||||
u_int8_t reserved4_4567 :4;
|
||||
u_int8_t reserved5;
|
||||
u_int8_t reserved6;
|
||||
u_int8_t host_app_code :6; /* Host application code */
|
||||
u_int8_t host_app_code :6; /* host application code */
|
||||
u_int8_t reserved7_67 :2;
|
||||
u_int8_t session_format; /* Session format */
|
||||
u_int8_t session_format; /* session format */
|
||||
#define CDR_SESS_CDROM 0x00
|
||||
#define CDR_SESS_CDI 0x10
|
||||
#define CDR_SESS_CDROM_XA 0x20
|
||||
|
||||
u_int8_t reserved9;
|
||||
u_int32_t packet_size; /* Packet size in bytes */
|
||||
u_int16_t audio_pause_length; /* Audio pause length in secs */
|
||||
u_int32_t packet_size; /* packet size in bytes */
|
||||
u_int16_t audio_pause_length; /* audio pause length in secs */
|
||||
u_int8_t media_catalog_number[16];
|
||||
u_int8_t isr_code[16];
|
||||
u_int8_t sub_hdr_byte0;
|
||||
@ -284,75 +275,72 @@ struct write_param {
|
||||
*/
|
||||
|
||||
} __attribute__((packed));
|
||||
/*
|
||||
* CDROM Read Track Information structure
|
||||
*/
|
||||
|
||||
/* CDROM Read Track Information structure */
|
||||
struct acd_track_info {
|
||||
u_int16_t data_length;
|
||||
u_int8_t track_number; /* Current track number */
|
||||
u_int8_t session_number; /* Current session number */
|
||||
u_int8_t track_number; /* current track number */
|
||||
u_int8_t session_number; /* current session number */
|
||||
u_int8_t reserved4;
|
||||
u_int8_t track_mode :4; /* Mode of this track */
|
||||
u_int8_t copy :1; /* Generation stamp */
|
||||
u_int8_t damage :1; /* Damaged track */
|
||||
u_int8_t track_mode :4; /* mode of this track */
|
||||
u_int8_t copy :1; /* generation stamp */
|
||||
u_int8_t damage :1; /* damaged track */
|
||||
u_int8_t reserved5_67 :2;
|
||||
u_int8_t data_mode :4; /* Data mode of this disc */
|
||||
u_int8_t fp :1; /* Fixed packet */
|
||||
u_int8_t packet :1; /* Packet track */
|
||||
u_int8_t blank :1; /* Blank (empty) track */
|
||||
u_int8_t rt :1; /* Reserved track */
|
||||
u_int8_t data_mode :4; /* data mode of this disc */
|
||||
u_int8_t fp :1; /* fixed packet */
|
||||
u_int8_t packet :1; /* packet track */
|
||||
u_int8_t blank :1; /* blank (empty) track */
|
||||
u_int8_t rt :1; /* reserved track */
|
||||
u_int8_t nwa_valid :1; /* next_writeable_addr field valid */
|
||||
u_int8_t reserved7_17 :7;
|
||||
u_int track_start_addr; /* Start of this track */
|
||||
u_int next_writeable_addr; /* Next writeable addr on this disc */
|
||||
u_int free_blocks; /* Free block on this disc */
|
||||
u_int fixed_packet_size; /* Size of packets on this track */
|
||||
u_int track_length; /* Length of this track */
|
||||
u_int track_start_addr; /* start of this track */
|
||||
u_int next_writeable_addr; /* next writeable addr on this disc */
|
||||
u_int free_blocks; /* free block on this disc */
|
||||
u_int fixed_packet_size; /* size of packets on this track */
|
||||
u_int track_length; /* length of this track */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing an ATAPI CDROM device
|
||||
*/
|
||||
/* Structure describing an ATAPI CDROM device */
|
||||
struct acd_softc {
|
||||
struct atapi_softc *atp; /* Controller structure */
|
||||
int32_t lun; /* Logical device unit */
|
||||
int32_t flags; /* Device state flags */
|
||||
int32_t refcnt; /* The number of raw opens */
|
||||
struct atapi_softc *atp; /* controller structure */
|
||||
int32_t lun; /* logical device unit */
|
||||
int32_t flags; /* device state flags */
|
||||
int32_t refcnt; /* the number of raw opens */
|
||||
struct buf_queue_head buf_queue; /* Queue of i/o requests */
|
||||
struct toc toc; /* Table of disc contents */
|
||||
struct toc toc; /* table of disc contents */
|
||||
struct {
|
||||
u_int32_t volsize; /* Volume size in blocks */
|
||||
u_int32_t blksize; /* Block size in bytes */
|
||||
} info;
|
||||
struct audiopage au; /* Audio page info */
|
||||
struct cappage cap; /* Capabilities page info */
|
||||
struct audiopage aumask; /* Audio page mask */
|
||||
struct { /* Subchannel info */
|
||||
u_int8_t void0;
|
||||
u_int8_t audio_status;
|
||||
u_int16_t data_length;
|
||||
u_int8_t data_format;
|
||||
u_int8_t control;
|
||||
u_int8_t track;
|
||||
u_int8_t indx;
|
||||
u_int32_t abslba;
|
||||
u_int32_t rellba;
|
||||
u_int32_t volsize; /* volume size in blocks */
|
||||
u_int32_t blksize; /* block size in bytes */
|
||||
} info;
|
||||
struct audiopage au; /* audio page info */
|
||||
struct cappage cap; /* capabilities page info */
|
||||
struct audiopage aumask; /* audio page mask */
|
||||
struct { /* subchannel info */
|
||||
u_int8_t void0;
|
||||
u_int8_t audio_status;
|
||||
u_int16_t data_length;
|
||||
u_int8_t data_format;
|
||||
u_int8_t control;
|
||||
u_int8_t track;
|
||||
u_int8_t indx;
|
||||
u_int32_t abslba;
|
||||
u_int32_t rellba;
|
||||
} subchan;
|
||||
struct changer *changer_info; /* Changer info */
|
||||
int32_t slot; /* This lun's slot number */
|
||||
u_int32_t block_size; /* Blocksize currently used */
|
||||
u_int8_t dummy; /* Use dummy writes */
|
||||
u_int8_t speed; /* Select drive speed */
|
||||
u_int32_t next_writeable_lba; /* Next writable position */
|
||||
struct wormio_prepare_track preptrack; /* Scratch region */
|
||||
struct changer *changer_info; /* changer info */
|
||||
int32_t slot; /* this lun's slot number */
|
||||
u_int32_t block_size; /* blocksize currently used */
|
||||
u_int8_t dummy; /* use dummy writes */
|
||||
u_int8_t speed; /* select drive speed */
|
||||
u_int32_t next_writeable_lba; /* next writable position */
|
||||
struct wormio_prepare_track preptrack; /* scratch region */
|
||||
struct devstat *stats; /* devstat entry */
|
||||
#ifdef DEVFS
|
||||
void *ra_devfs_token;
|
||||
void *rc_devfs_token;
|
||||
void *a_devfs_token;
|
||||
void *c_devfs_token;
|
||||
void *a_cdevfs_token;
|
||||
void *c_cdevfs_token;
|
||||
void *a_bdevfs_token;
|
||||
void *c_bdevfs_token;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define CDRIOCBLANK _IO('c',100) /* Blank a CDRW disc */
|
||||
#define CDRIOCBLANK _IO('c',100) /* blank a CDRW disc */
|
||||
#define CDRIOCNEXTWRITEABLEADDR _IOR('c',101,int)
|
||||
|
434
sys/dev/ata/atapi-fd.c
Normal file
434
sys/dev/ata/atapi-fd.c
Normal file
@ -0,0 +1,434 @@
|
||||
/*-
|
||||
* Copyright (c) 1998,1999 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
#include "atapifd.h"
|
||||
#include "opt_devfs.h"
|
||||
|
||||
#if NATA > 0 && NATAPIFD > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/diskslice.h>
|
||||
#include <sys/devicestat.h>
|
||||
#include <sys/cdio.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef DEVFS
|
||||
#include <sys/devfsext.h>
|
||||
#endif
|
||||
#include <dev/ata/ata-all.h>
|
||||
#include <dev/ata/atapi-all.h>
|
||||
#include <dev/ata/atapi-fd.h>
|
||||
|
||||
static d_open_t afdopen;
|
||||
static d_close_t afdclose;
|
||||
static d_read_t afdread;
|
||||
static d_write_t afdwrite;
|
||||
static d_ioctl_t afdioctl;
|
||||
static d_strategy_t afdstrategy;
|
||||
|
||||
#define CDEV_MAJOR 87
|
||||
#define BDEV_MAJOR 1
|
||||
|
||||
static struct cdevsw afd_cdevsw = {
|
||||
afdopen, afdclose, afdread, afdwrite,
|
||||
afdioctl, nostop, nullreset, nodevtotty,
|
||||
seltrue, nommap, afdstrategy, "afd",
|
||||
NULL, -1 };
|
||||
|
||||
#define NUNIT 8
|
||||
#define UNIT(d) ((minor(d) >> 3) & 3)
|
||||
|
||||
#define F_OPEN 0x0001 /* The device is opened */
|
||||
#define F_MEDIA_CHANGED 0x0002 /* The media have changed */
|
||||
|
||||
static struct afd_softc *afdtab[NUNIT]; /* Drive info by unit number */
|
||||
static int32_t afdnlun = 0; /* Number of config'd drives */
|
||||
|
||||
int32_t afdattach(struct atapi_softc *);
|
||||
static int32_t afd_sense(struct afd_softc *);
|
||||
static void afd_describe(struct afd_softc *);
|
||||
static void afd_strategy(struct buf *);
|
||||
static void afd_start(struct afd_softc *);
|
||||
static void afd_done(struct atapi_request *);
|
||||
static int32_t afd_start_device(struct afd_softc *, int32_t);
|
||||
static int32_t afd_lock_device(struct afd_softc *, int32_t);
|
||||
static int32_t afd_eject(struct afd_softc *, int32_t);
|
||||
static void afd_drvinit(void *);
|
||||
|
||||
int32_t
|
||||
afdattach(struct atapi_softc *atp)
|
||||
{
|
||||
struct afd_softc *fdp;
|
||||
|
||||
if (afdnlun >= NUNIT) {
|
||||
printf("afd: too many units\n");
|
||||
return -1;
|
||||
}
|
||||
fdp = malloc(sizeof(struct afd_softc), M_TEMP, M_NOWAIT);
|
||||
if (!fdp) {
|
||||
printf("afd: out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
bzero(fdp, sizeof(struct afd_softc));
|
||||
bufq_init(&fdp->buf_queue);
|
||||
fdp->atp = atp;
|
||||
fdp->lun = afdnlun;
|
||||
fdp->flags = F_MEDIA_CHANGED;
|
||||
|
||||
if (afd_sense(fdp)) {
|
||||
free(fdp, M_TEMP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
afd_describe(fdp);
|
||||
afdtab[afdnlun++] = fdp;
|
||||
devstat_add_entry(&fdp->stats, "afd", fdp->lun, DEV_BSIZE,
|
||||
DEVSTAT_NO_ORDERED_TAGS,
|
||||
DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE,
|
||||
0x178);
|
||||
#ifdef DEVFS
|
||||
fdp->cdevs_token = devfs_add_devswf(&afd_cdevsw, dkmakeminor(fdp->lun, 0,0),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR,
|
||||
0640, "rafd%d", fdp->lun);
|
||||
fdp->bdevs_token = devfs_add_devswf(&afd_cdevsw, dkmakeminor(fdp->lun, 0,0),
|
||||
DV_BLK, UID_ROOT, GID_OPERATOR,
|
||||
0640, "afd%d", fdp->lun);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afd_sense(struct afd_softc *fdp)
|
||||
{
|
||||
int32_t error, count;
|
||||
int8_t buffer[256];
|
||||
int8_t ccb[16] = { ATAPI_MODE_SENSE, 0, ATAPI_REWRITEABLE_CAP_PAGE,
|
||||
0, 0, 0, 0, sizeof(buffer)>>8, sizeof(buffer) & 0xff,
|
||||
0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
bzero(buffer, sizeof(buffer));
|
||||
/* Get drive capabilities, some drives needs this repeated */
|
||||
for (count = 0 ; count < 5 ; count++) {
|
||||
if (!(error = atapi_queue_cmd(fdp->atp, ccb, buffer, sizeof(buffer),
|
||||
A_READ, NULL, NULL, NULL)))
|
||||
break;
|
||||
}
|
||||
#ifdef AFD_DEBUG
|
||||
atapi_dump("afd: sense", buffer, sizeof(buffer));
|
||||
#endif
|
||||
if (error)
|
||||
return error;
|
||||
bcopy(buffer, &fdp->header, sizeof(struct afd_header));
|
||||
bcopy(buffer+sizeof(struct afd_header), &fdp->cap,
|
||||
sizeof(struct afd_cappage));
|
||||
if (fdp->cap.page_code != ATAPI_REWRITEABLE_CAP_PAGE)
|
||||
return 1;
|
||||
fdp->cap.cylinders = ntohs(fdp->cap.cylinders);
|
||||
fdp->cap.sector_size = ntohs(fdp->cap.sector_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
afd_describe(struct afd_softc *fdp)
|
||||
{
|
||||
int8_t model_buf[40+1];
|
||||
int8_t revision_buf[8+1];
|
||||
|
||||
bpack(fdp->atp->atapi_parm->model, model_buf, sizeof(model_buf));
|
||||
bpack(fdp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf));
|
||||
printf("afd%d: <%s/%s> rewriteable drive at ata%d as %s\n",
|
||||
fdp->lun, model_buf, revision_buf,
|
||||
fdp->atp->controller->unit,
|
||||
(fdp->atp->unit == ATA_MASTER) ? "master" : "slave ");
|
||||
printf("afd%d: %luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n",
|
||||
afdnlun,
|
||||
(fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) /
|
||||
((1024L * 1024L) / fdp->cap.sector_size),
|
||||
fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors,
|
||||
fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
|
||||
fdp->cap.sector_size);
|
||||
printf("afd%d: ", fdp->lun);
|
||||
switch (fdp->header.medium_type) {
|
||||
default: printf("Unknown media (0x%x)", fdp->header.medium_type);
|
||||
}
|
||||
if (fdp->header.wp) printf(", writeprotected");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
struct afd_softc *fdp;
|
||||
struct disklabel label;
|
||||
int32_t lun = UNIT(dev);
|
||||
|
||||
if (lun >= afdnlun || !(fdp = afdtab[lun]))
|
||||
return ENXIO;
|
||||
|
||||
fdp->flags &= ~F_MEDIA_CHANGED;
|
||||
afd_lock_device(fdp, 1);
|
||||
if (afd_sense(fdp))
|
||||
printf("afd%d: sense media type failed\n", fdp->lun);
|
||||
|
||||
/* build disklabel and initilize slice tables */
|
||||
bzero(&label, sizeof label);
|
||||
label.d_secsize = fdp->cap.sector_size;
|
||||
label.d_nsectors = fdp->cap.sectors;
|
||||
label.d_ntracks = fdp->cap.heads;
|
||||
label.d_ncylinders = fdp->cap.cylinders;
|
||||
label.d_secpercyl = fdp->cap.heads * fdp->cap.sectors;
|
||||
label.d_secperunit = fdp->cap.heads * fdp->cap.sectors * fdp->cap.cylinders;
|
||||
|
||||
/* Initialize slice tables. */
|
||||
return dsopen("afd", dev, fmt, 0, &fdp->slices, &label, afd_strategy,
|
||||
(ds_setgeom_t *)NULL, &afd_cdevsw);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
int32_t lun = UNIT(dev);
|
||||
struct afd_softc *fdp;
|
||||
|
||||
if (lun >= afdnlun || !(fdp = afdtab[lun]))
|
||||
return ENXIO;
|
||||
|
||||
dsclose(dev, fmt, fdp->slices);
|
||||
if(!dsisopen(fdp->slices))
|
||||
afd_lock_device(fdp, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afdread(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return physio(afdstrategy, NULL, dev, 1, minphys, uio);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afdwrite(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return physio(afdstrategy, NULL, dev, 0, minphys, uio);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
{
|
||||
int32_t lun = UNIT(dev);
|
||||
int32_t error = 0;
|
||||
struct afd_softc *fdp;
|
||||
|
||||
if (lun >= afdnlun || !(fdp = afdtab[lun]))
|
||||
return ENXIO;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case CDIOCEJECT:
|
||||
if ((fdp->flags & F_OPEN) && fdp->refcnt)
|
||||
return EBUSY;
|
||||
return afd_eject(fdp, 0);
|
||||
|
||||
case CDIOCCLOSE:
|
||||
if ((fdp->flags & F_OPEN) && fdp->refcnt)
|
||||
return 0;
|
||||
return afd_eject(fdp, 1);
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
afdstrategy(struct buf *bp)
|
||||
{
|
||||
int32_t lun = UNIT(bp->b_dev);
|
||||
struct afd_softc *fdp = afdtab[lun];
|
||||
int32_t x;
|
||||
|
||||
if (bp->b_bcount == 0) {
|
||||
bp->b_resid = 0;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
if (dscheck(bp, fdp->slices) <= 0) {
|
||||
x = splbio();
|
||||
biodone(bp);
|
||||
splx(x);
|
||||
return;
|
||||
}
|
||||
x = splbio();
|
||||
bufq_insert_tail(&fdp->buf_queue, bp);
|
||||
afd_start(fdp);
|
||||
splx(x);
|
||||
}
|
||||
|
||||
static void
|
||||
afd_strategy(struct buf *bp)
|
||||
{
|
||||
afdstrategy(bp);
|
||||
}
|
||||
|
||||
static void
|
||||
afd_start(struct afd_softc *fdp)
|
||||
{
|
||||
struct buf *bp = bufq_first(&fdp->buf_queue);
|
||||
u_int32_t lba, count;
|
||||
int8_t ccb[16];
|
||||
|
||||
if (!bp)
|
||||
return;
|
||||
bzero(ccb, sizeof(ccb));
|
||||
bufq_remove(&fdp->buf_queue, bp);
|
||||
|
||||
/* Should reject all queued entries if media have changed. */
|
||||
if (fdp->flags & F_MEDIA_CHANGED) {
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
lba = bp->b_blkno / (fdp->cap.sector_size / DEV_BSIZE);
|
||||
count = (bp->b_bcount + (fdp->cap.sector_size - 1)) / fdp->cap.sector_size;
|
||||
|
||||
if (bp->b_flags & B_READ)
|
||||
ccb[0] = ATAPI_READ_BIG;
|
||||
else
|
||||
ccb[0] = ATAPI_WRITE_BIG;
|
||||
|
||||
ccb[1] = 0;
|
||||
ccb[2] = lba>>24;
|
||||
ccb[3] = lba>>16;
|
||||
ccb[4] = lba>>8;
|
||||
ccb[5] = lba;
|
||||
ccb[7] = count>>8;
|
||||
ccb[8] = count;
|
||||
|
||||
devstat_start_transaction(&fdp->stats);
|
||||
|
||||
atapi_queue_cmd(fdp->atp, ccb, bp->b_data, bp->b_bcount,
|
||||
(bp->b_flags & B_READ) ? A_READ : 0, afd_done, fdp, bp);
|
||||
}
|
||||
|
||||
static void
|
||||
afd_done(struct atapi_request *request)
|
||||
{
|
||||
struct buf *bp = request->bp;
|
||||
struct afd_softc *fdp = request->driver;
|
||||
|
||||
devstat_end_transaction(&fdp->stats, bp->b_bcount-request->bytecount,
|
||||
DEVSTAT_TAG_NONE,
|
||||
(bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE);
|
||||
|
||||
if (request->result) {
|
||||
printf("afd_done: ");
|
||||
atapi_error(request->device, request->result);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
else
|
||||
bp->b_resid = request->bytecount;
|
||||
biodone(bp);
|
||||
afd_start(fdp);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afd_start_device(struct afd_softc *fdp, int32_t start)
|
||||
{
|
||||
int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afd_lock_device(struct afd_softc *fdp, int32_t lock)
|
||||
{
|
||||
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
afd_eject(struct afd_softc *fdp, int32_t close)
|
||||
{
|
||||
int32_t error;
|
||||
|
||||
error = afd_start_device(fdp, 0);
|
||||
if ((error & ATAPI_SK_MASK) &&
|
||||
((error & ATAPI_SK_MASK) == ATAPI_SK_NOT_READY ||
|
||||
(error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION)) {
|
||||
|
||||
if (!close)
|
||||
return 0;
|
||||
if ((error = afd_start_device(fdp, 3)))
|
||||
return error;
|
||||
afd_lock_device(fdp, 1);
|
||||
return 0;
|
||||
}
|
||||
if (error) {
|
||||
atapi_error(fdp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
if (close)
|
||||
return 0;
|
||||
|
||||
tsleep((caddr_t) &lbolt, PRIBIO, "afdej1", 0);
|
||||
tsleep((caddr_t) &lbolt, PRIBIO, "afdej2", 0);
|
||||
afd_lock_device(fdp, 0);
|
||||
fdp->flags |= F_MEDIA_CHANGED;
|
||||
return afd_start_device(fdp, 2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
afd_drvinit(void *unused)
|
||||
{
|
||||
static afd_devsw_installed = 0;
|
||||
|
||||
if (!afd_devsw_installed) {
|
||||
cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &afd_cdevsw);
|
||||
afd_devsw_installed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
SYSINIT(afddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, afd_drvinit, NULL)
|
||||
#endif /* NATA & NATAPIFD */
|
90
sys/dev/ata/atapi-fd.h
Normal file
90
sys/dev/ata/atapi-fd.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*-
|
||||
* Copyright (c) 1998,1999 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* MODE SENSE parameter header */
|
||||
struct afd_header {
|
||||
u_int16_t data_length;
|
||||
u_int8_t medium_type;
|
||||
#define MFD_2DD_UN 0x10
|
||||
#define MFD_2DD 0x11
|
||||
#define MFD_2HD_UN 0x20
|
||||
#define MFD_2HD_12_98 0x22
|
||||
#define MFD_2HD_12 0x23
|
||||
#define MFD_2HD_144 0x24
|
||||
#define MFD_LS120 0x31
|
||||
|
||||
#define MFD_UNKNOWN 0x00
|
||||
#define MFD_NO_DISC 0x70
|
||||
#define MFD_DOOR_OPEN 0x71
|
||||
#define MFD_FMT_ERROR 0x72
|
||||
|
||||
u_int8_t reserved0 :7;
|
||||
u_int8_t wp :1; /* write protect */
|
||||
u_int8_t unused[4];
|
||||
};
|
||||
|
||||
/* ATAPI Rewriteable drive Capabilities and Mechanical Status Page */
|
||||
#define ATAPI_REWRITEABLE_CAP_PAGE 0x05
|
||||
|
||||
struct afd_cappage {
|
||||
u_int8_t page_code :6;
|
||||
u_int8_t reserved1_6 :1;
|
||||
u_int8_t ps :1; /* page save supported */
|
||||
u_int8_t page_length; /* page length */
|
||||
u_int16_t transfer_rate; /* in kilobits per second */
|
||||
u_int8_t heads; /* number of heads */
|
||||
u_int8_t sectors; /* number of sectors per track */
|
||||
u_int16_t sector_size; /* number of bytes per sector */
|
||||
u_int16_t cylinders; /* number of cylinders */
|
||||
u_int8_t reserved10[10];
|
||||
u_int8_t motor_delay; /* motor off delay */
|
||||
u_int8_t reserved21[7];
|
||||
u_int16_t rpm; /* rotations per minute */
|
||||
u_int8_t reserved30[2];
|
||||
};
|
||||
|
||||
|
||||
struct afd_softc {
|
||||
struct atapi_softc *atp; /* controller structure */
|
||||
int32_t lun; /* logical device unit */
|
||||
int32_t flags; /* device state flags */
|
||||
int32_t refcnt; /* the number of raw opens */
|
||||
int32_t maxblks; /* transfer size limit */
|
||||
struct buf_queue_head buf_queue; /* queue of i/o requests */
|
||||
struct afd_header header; /* capabilities page info */
|
||||
struct afd_cappage cap; /* capabilities page info */
|
||||
struct diskslices *slices; /* virtual drives */
|
||||
struct devstat stats;
|
||||
#ifdef DEVFS
|
||||
void *cdevs_token;
|
||||
void *bdevs_token;
|
||||
#endif
|
||||
};
|
||||
|
@ -25,7 +25,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-tape.c,v 1.5 1999/03/01 21:03:15 sos Exp sos $
|
||||
* $Id: atapi-tape.c,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -41,6 +41,7 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/mtio.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/devicestat.h>
|
||||
#ifdef DEVFS
|
||||
#include <sys/devfsext.h>
|
||||
@ -50,21 +51,21 @@
|
||||
#include <dev/ata/atapi-all.h>
|
||||
#include <dev/ata/atapi-tape.h>
|
||||
|
||||
static d_open_t astopen;
|
||||
static d_read_t astread;
|
||||
static d_write_t astwrite;
|
||||
static d_close_t astclose;
|
||||
static d_ioctl_t astioctl;
|
||||
static d_strategy_t aststrategy;
|
||||
static d_open_t astopen;
|
||||
static d_close_t astclose;
|
||||
static d_read_t astread;
|
||||
static d_write_t astwrite;
|
||||
static d_ioctl_t astioctl;
|
||||
static d_strategy_t aststrategy;
|
||||
|
||||
#define CDEV_MAJOR 90
|
||||
#define BDEV_MAJOR 24
|
||||
|
||||
static struct cdevsw ast_cdevsw = {
|
||||
astopen, astclose, astread, astwrite,
|
||||
astioctl, nostop, nullreset, nodevtotty,
|
||||
seltrue, nommap, aststrategy, "ast",
|
||||
NULL, -1 };
|
||||
astopen, astclose, astread, astwrite,
|
||||
astioctl, nostop, nullreset, nodevtotty,
|
||||
seltrue, nommap, aststrategy, "ast",
|
||||
NULL, -1 };
|
||||
|
||||
static u_int32_t ast_total = 0;
|
||||
|
||||
@ -123,12 +124,11 @@ astattach(struct atapi_softc *atp)
|
||||
DEVSTAT_NO_ORDERED_TAGS,
|
||||
DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
|
||||
0x178);
|
||||
|
||||
|
||||
#ifdef DEVFS
|
||||
t->cdevs = devfs_add_devswf(&ast_cdevsw, 0, DV_CHR, UID_ROOT, GID_OPERATOR,
|
||||
0640, "rast%d", t->lun);
|
||||
#endif /* DEVFS */
|
||||
stp->cdevs_token = devfs_add_devswf(&ast_cdevsw, dkmakeminor(stp->lun, 0,0),
|
||||
DV_CHR, UID_ROOT, GID_OPERATOR, 0640,
|
||||
"rast%d", stp->lun);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -209,14 +209,14 @@ ast_describe(struct ast_softc *stp)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int
|
||||
static int32_t
|
||||
astopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
int32_t lun = UNIT(dev);
|
||||
struct ast_softc *stp;
|
||||
|
||||
if (lun >= astnlun || !(stp = asttab[lun]))
|
||||
return(ENXIO);
|
||||
return ENXIO;
|
||||
if (stp->flags == F_OPEN)
|
||||
return EBUSY;
|
||||
if (ast_sense(stp))
|
||||
@ -225,17 +225,17 @@ astopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
|
||||
stp->flags |= F_OPEN;
|
||||
ast_total = 0;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
static int32_t
|
||||
astclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
{
|
||||
int32_t lun = UNIT(dev);
|
||||
struct ast_softc *stp;
|
||||
|
||||
if (lun >= astnlun || !(stp = asttab[lun]))
|
||||
return(ENXIO);
|
||||
return ENXIO;
|
||||
|
||||
/* Flush buffers, some drives fail here, but they should report ctl = 0 */
|
||||
if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN))
|
||||
@ -254,111 +254,22 @@ astclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
|
||||
printf("ast%d: %ud total bytes transferred\n", stp->lun, ast_total);
|
||||
#endif
|
||||
stp->flags &= ~F_CTL_WARN;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
astread(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return (physio(aststrategy, NULL, dev, 1, minphys, uio));
|
||||
return physio(aststrategy, NULL, dev, 1, minphys, uio);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
astwrite(dev_t dev, struct uio *uio, int32_t ioflag)
|
||||
{
|
||||
return (physio(aststrategy, NULL, dev, 0, minphys, uio));
|
||||
return physio(aststrategy, NULL, dev, 0, minphys, uio);
|
||||
}
|
||||
|
||||
void
|
||||
aststrategy(struct buf *bp)
|
||||
{
|
||||
int32_t lun = UNIT(bp->b_dev);
|
||||
struct ast_softc *stp = asttab[lun];
|
||||
int32_t x;
|
||||
|
||||
/* If it's a null transfer, return immediatly. */
|
||||
if (bp->b_bcount == 0) {
|
||||
bp->b_resid = 0;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for != blocksize requests */
|
||||
if (bp->b_bcount % stp->blksize) {
|
||||
printf("ast%d: bad request, must be multiple of %d\n",
|
||||
lun, stp->blksize);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
if (bp->b_bcount > stp->blksize * stp->cap.ctl) {
|
||||
if ((stp->flags & F_CTL_WARN) == 0) {
|
||||
printf("ast%d: WARNING: CTL exceeded %ld>%d\n",
|
||||
lun, bp->b_bcount, stp->blksize * stp->cap.ctl);
|
||||
stp->flags |= F_CTL_WARN;
|
||||
}
|
||||
}
|
||||
|
||||
x = splbio();
|
||||
ast_total += bp->b_bcount;
|
||||
bufq_insert_tail(&stp->buf_queue, bp);
|
||||
ast_start(stp);
|
||||
splx(x);
|
||||
}
|
||||
|
||||
static void
|
||||
ast_start(struct ast_softc *stp)
|
||||
{
|
||||
struct buf *bp = bufq_first(&stp->buf_queue);
|
||||
u_long blkcount;
|
||||
int8_t ccb[16];
|
||||
|
||||
if (!bp)
|
||||
return;
|
||||
bzero(ccb, sizeof(ccb));
|
||||
bufq_remove(&stp->buf_queue, bp);
|
||||
blkcount = bp->b_bcount / stp->blksize;
|
||||
if (bp->b_flags & B_READ) {
|
||||
ccb[0] = ATAPI_TAPE_READ_CMD;
|
||||
} else {
|
||||
ccb[0] = ATAPI_TAPE_WRITE_CMD;
|
||||
stp->flags |= F_DATA_WRITTEN;
|
||||
}
|
||||
ccb[1] = 1;
|
||||
ccb[2] = blkcount>>16;
|
||||
ccb[3] = blkcount>>8;
|
||||
ccb[4] = blkcount;
|
||||
|
||||
devstat_start_transaction(&stp->stats);
|
||||
|
||||
atapi_queue_cmd(stp->atp, ccb, bp->b_data, bp->b_bcount,
|
||||
(bp->b_flags & B_READ) ? A_READ : 0, ast_done, stp, bp);
|
||||
}
|
||||
|
||||
static void
|
||||
ast_done(struct atapi_request *request)
|
||||
{
|
||||
struct buf *bp = request->bp;
|
||||
struct ast_softc *stp = request->driver;
|
||||
|
||||
devstat_end_transaction(&stp->stats, bp->b_bcount-request->bytecount,
|
||||
DEVSTAT_TAG_NONE,
|
||||
(bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE);
|
||||
|
||||
if (request->result) {
|
||||
printf("ast_done: ");
|
||||
atapi_error(request->device, request->result);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
else
|
||||
bp->b_resid = request->bytecount;
|
||||
biodone(bp);
|
||||
ast_start(stp);
|
||||
}
|
||||
|
||||
int32_t
|
||||
static int32_t
|
||||
astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
{
|
||||
int32_t lun = UNIT(dev);
|
||||
@ -444,12 +355,100 @@ astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
|
||||
return error;
|
||||
}
|
||||
default:
|
||||
return(ENOTTY);
|
||||
return ENOTTY;
|
||||
}
|
||||
return(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
aststrategy(struct buf *bp)
|
||||
{
|
||||
int32_t lun = UNIT(bp->b_dev);
|
||||
struct ast_softc *stp = asttab[lun];
|
||||
int32_t x;
|
||||
|
||||
/* If it's a null transfer, return immediatly. */
|
||||
if (bp->b_bcount == 0) {
|
||||
bp->b_resid = 0;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for != blocksize requests */
|
||||
if (bp->b_bcount % stp->blksize) {
|
||||
printf("ast%d: bad request, must be multiple of %d\n",
|
||||
lun, stp->blksize);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
if (bp->b_bcount > stp->blksize * stp->cap.ctl) {
|
||||
if ((stp->flags & F_CTL_WARN) == 0) {
|
||||
printf("ast%d: WARNING: CTL exceeded %ld>%d\n",
|
||||
lun, bp->b_bcount, stp->blksize * stp->cap.ctl);
|
||||
stp->flags |= F_CTL_WARN;
|
||||
}
|
||||
}
|
||||
|
||||
x = splbio();
|
||||
ast_total += bp->b_bcount;
|
||||
bufq_insert_tail(&stp->buf_queue, bp);
|
||||
ast_start(stp);
|
||||
splx(x);
|
||||
}
|
||||
|
||||
static void
|
||||
ast_start(struct ast_softc *stp)
|
||||
{
|
||||
struct buf *bp = bufq_first(&stp->buf_queue);
|
||||
u_int32_t blkcount;
|
||||
int8_t ccb[16];
|
||||
|
||||
if (!bp)
|
||||
return;
|
||||
bzero(ccb, sizeof(ccb));
|
||||
bufq_remove(&stp->buf_queue, bp);
|
||||
blkcount = bp->b_bcount / stp->blksize;
|
||||
if (bp->b_flags & B_READ) {
|
||||
ccb[0] = ATAPI_TAPE_READ_CMD;
|
||||
} else {
|
||||
ccb[0] = ATAPI_TAPE_WRITE_CMD;
|
||||
stp->flags |= F_DATA_WRITTEN;
|
||||
}
|
||||
ccb[1] = 1;
|
||||
ccb[2] = blkcount>>16;
|
||||
ccb[3] = blkcount>>8;
|
||||
ccb[4] = blkcount;
|
||||
|
||||
devstat_start_transaction(&stp->stats);
|
||||
|
||||
atapi_queue_cmd(stp->atp, ccb, bp->b_data, bp->b_bcount,
|
||||
(bp->b_flags & B_READ) ? A_READ : 0, ast_done, stp, bp);
|
||||
}
|
||||
|
||||
static void
|
||||
ast_done(struct atapi_request *request)
|
||||
{
|
||||
struct buf *bp = request->bp;
|
||||
struct ast_softc *stp = request->driver;
|
||||
|
||||
devstat_end_transaction(&stp->stats, bp->b_bcount-request->bytecount,
|
||||
DEVSTAT_TAG_NONE,
|
||||
(bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE);
|
||||
|
||||
if (request->result) {
|
||||
atapi_error(request->device, request->result);
|
||||
bp->b_error = EIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
}
|
||||
else
|
||||
bp->b_resid = request->bytecount;
|
||||
biodone(bp);
|
||||
ast_start(stp);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ast_space_cmd(struct ast_softc *stp, u_int8_t function, u_int32_t count)
|
||||
{
|
||||
int32_t error;
|
||||
@ -463,14 +462,13 @@ ast_space_cmd(struct ast_softc *stp, u_int8_t function, u_int32_t count)
|
||||
ccb[4] = count;
|
||||
|
||||
if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){
|
||||
printf("ast_space_cmd: ");
|
||||
atapi_error(stp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
ast_write_filemark(struct ast_softc *stp, u_int8_t function)
|
||||
{
|
||||
int32_t error;
|
||||
@ -487,14 +485,13 @@ ast_write_filemark(struct ast_softc *stp, u_int8_t function)
|
||||
ccb[4] = function;
|
||||
|
||||
if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){
|
||||
printf("ast_write_filemark: ");
|
||||
atapi_error(stp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
ast_load_unload(struct ast_softc *stp, u_int8_t function)
|
||||
{
|
||||
int32_t error;
|
||||
@ -505,14 +502,13 @@ ast_load_unload(struct ast_softc *stp, u_int8_t function)
|
||||
ccb[4] = function;
|
||||
|
||||
if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){
|
||||
printf("ast_load_unload: ");
|
||||
atapi_error(stp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
ast_erase(struct ast_softc *stp)
|
||||
{
|
||||
int32_t error;
|
||||
@ -526,14 +522,13 @@ ast_erase(struct ast_softc *stp)
|
||||
ccb[1] = 3;
|
||||
|
||||
if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){
|
||||
printf("ast_erase: ");
|
||||
atapi_error(stp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
ast_rewind(struct ast_softc *stp)
|
||||
{
|
||||
int32_t error;
|
||||
@ -543,7 +538,6 @@ ast_rewind(struct ast_softc *stp)
|
||||
ccb[0] = ATAPI_TAPE_REWIND;
|
||||
|
||||
if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){
|
||||
printf("ast_rewind: ");
|
||||
atapi_error(stp->atp, error);
|
||||
return EIO;
|
||||
}
|
||||
|
@ -1,3 +1,32 @@
|
||||
/*-
|
||||
* Copyright (c) 1998,1999 Søren Schmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: atapi-tape.h,v 1.1 1999/03/01 21:19:18 sos Exp $
|
||||
*/
|
||||
|
||||
/* ATAPI tape commands not in std ATAPI command set */
|
||||
#define ATAPI_TAPE_REWIND 0x01
|
||||
@ -18,95 +47,89 @@
|
||||
|
||||
#define DSC_POLL_INTERVAL 10
|
||||
|
||||
/*
|
||||
* MODE SENSE parameter header
|
||||
*/
|
||||
/* MODE SENSE parameter header */
|
||||
struct ast_header {
|
||||
u_int8_t data_length; /* Total length of data */
|
||||
u_int8_t medium_type; /* Medium type (if any) */
|
||||
u_int8_t dsp; /* Device specific parameter */
|
||||
u_int8_t bdl; /* Block Descriptor Length */
|
||||
u_int8_t data_length; /* total length of data */
|
||||
u_int8_t medium_type; /* medium type (if any) */
|
||||
u_int8_t dsp; /* device specific parameter */
|
||||
u_int8_t bdl; /* block Descriptor Length */
|
||||
};
|
||||
|
||||
/*
|
||||
* ATAPI tape drive Capabilities and Mechanical Status Page
|
||||
*/
|
||||
/* ATAPI tape drive Capabilities and Mechanical Status Page */
|
||||
#define ATAPI_TAPE_CAP_PAGE 0x2a
|
||||
|
||||
struct ast_cappage {
|
||||
u_int8_t page_code :6; /* Page code == 0x2a */
|
||||
u_int8_t page_code :6; /* page code == 0x2a */
|
||||
u_int8_t reserved1_67 :2;
|
||||
u_int8_t page_length; /* Page Length == 0x12 */
|
||||
u_int8_t page_length; /* page Length == 0x12 */
|
||||
u_int8_t reserved2;
|
||||
u_int8_t reserved3;
|
||||
u_int8_t readonly :1; /* Read Only Mode */
|
||||
u_int8_t readonly :1; /* read Only Mode */
|
||||
u_int8_t reserved4_1234 :4;
|
||||
u_int8_t reverse :1; /* Supports reverse direction */
|
||||
u_int8_t reverse :1; /* supports reverse direction */
|
||||
u_int8_t reserved4_67 :2;
|
||||
u_int8_t reserved5_012 :3;
|
||||
u_int8_t eformat :1; /* Supports ERASE formatting */
|
||||
u_int8_t eformat :1; /* supports ERASE formatting */
|
||||
u_int8_t reserved5_4 :1;
|
||||
u_int8_t qfa :1; /* Supports QFA formats */
|
||||
u_int8_t qfa :1; /* supports QFA formats */
|
||||
u_int8_t reserved5_67 :2;
|
||||
u_int8_t lock :1; /* Supports locking media */
|
||||
u_int8_t locked :1; /* The media is locked */
|
||||
u_int8_t prevent :1; /* Defaults to prevent state */
|
||||
u_int8_t eject :1; /* Supports eject */
|
||||
u_int8_t disconnect :1; /* Can break request > ctl */
|
||||
u_int8_t lock :1; /* supports locking media */
|
||||
u_int8_t locked :1; /* the media is locked */
|
||||
u_int8_t prevent :1; /* defaults to prevent state */
|
||||
u_int8_t eject :1; /* supports eject */
|
||||
u_int8_t disconnect :1; /* can break request > ctl */
|
||||
u_int8_t reserved6_5 :1;
|
||||
u_int8_t ecc :1; /* Supports error correction */
|
||||
u_int8_t compress :1; /* Supports data compression */
|
||||
u_int8_t ecc :1; /* supports error correction */
|
||||
u_int8_t compress :1; /* supports data compression */
|
||||
u_int8_t reserved7_0 :1;
|
||||
u_int8_t blk512 :1; /* Supports 512b block size */
|
||||
u_int8_t blk1024 :1; /* Supports 1024b block size */
|
||||
u_int8_t blk512 :1; /* supports 512b block size */
|
||||
u_int8_t blk1024 :1; /* supports 1024b block size */
|
||||
u_int8_t reserved7_3456 :4;
|
||||
u_int8_t slowb :1; /* Restricts byte count */
|
||||
u_int16_t max_speed; /* Supported speed in KBps */
|
||||
u_int16_t max_defects; /* Max stored defect entries */
|
||||
u_int16_t ctl; /* Continuous Transfer Limit */
|
||||
u_int16_t speed; /* Current Speed, in KBps */
|
||||
u_int16_t buffer_size; /* Buffer Size, in 512 bytes */
|
||||
u_int8_t slowb :1; /* restricts byte count */
|
||||
u_int16_t max_speed; /* supported speed in KBps */
|
||||
u_int16_t max_defects; /* max stored defect entries */
|
||||
u_int16_t ctl; /* continuous transfer limit */
|
||||
u_int16_t speed; /* current Speed, in KBps */
|
||||
u_int16_t buffer_size; /* buffer Size, in 512 bytes */
|
||||
u_int8_t reserved18;
|
||||
u_int8_t reserved19;
|
||||
};
|
||||
|
||||
/*
|
||||
* REQUEST SENSE structure
|
||||
*/
|
||||
/* REQUEST SENSE structure */
|
||||
struct ast_reqsense {
|
||||
u_int8_t error_code :7; /* Current or deferred errors */
|
||||
u_int8_t valid :1; /* Follows QIC-157C */
|
||||
u_int8_t reserved1; /* Segment Number - Reserved */
|
||||
u_int8_t sense_key :4; /* Sense Key */
|
||||
u_int8_t reserved2_4 :1; /* Reserved */
|
||||
u_int8_t ili :1; /* Incorrect Length Indicator */
|
||||
u_int8_t eom :1; /* End Of Medium */
|
||||
u_int8_t filemark :1; /* Filemark */
|
||||
u_int8_t info __attribute__((packed)); /* Cmd specific info */
|
||||
u_int8_t asl; /* Additional sense length (n-7) */
|
||||
u_int8_t command_specific; /* Additional cmd specific info */
|
||||
u_int8_t asc; /* Additional Sense Code */
|
||||
u_int8_t ascq; /* Additional Sense Code Qualifier */
|
||||
u_int8_t replaceable_unit_code; /* Field Replaceable Unit Code */
|
||||
u_int8_t sk_specific1 :7; /* Sense Key Specific */
|
||||
u_int8_t sksv :1; /* Sense Key Specific info valid */
|
||||
u_int8_t sk_specific2; /* Sense Key Specific */
|
||||
u_int8_t sk_specific3; /* Sense Key Specific */
|
||||
u_int8_t pad[2]; /* Padding */
|
||||
u_int8_t error_code :7; /* current or deferred errors */
|
||||
u_int8_t valid :1; /* follows QIC-157C */
|
||||
u_int8_t reserved1; /* Segment number - reserved */
|
||||
u_int8_t sense_key :4; /* sense key */
|
||||
u_int8_t reserved2_4 :1; /* reserved */
|
||||
u_int8_t ili :1; /* incorrect length indicator */
|
||||
u_int8_t eom :1; /* end of medium */
|
||||
u_int8_t filemark :1; /* filemark */
|
||||
u_int8_t info __attribute__((packed)); /* cmd specific info */
|
||||
u_int8_t asl; /* additional sense length (n-7) */
|
||||
u_int8_t command_specific; /* additional cmd specific info */
|
||||
u_int8_t asc; /* additional sense code */
|
||||
u_int8_t ascq; /* additional sense code qualifier */
|
||||
u_int8_t replaceable_unit_code; /* field replaceable unit code */
|
||||
u_int8_t sk_specific1 :7; /* sense key specific */
|
||||
u_int8_t sksv :1; /* sense key specific info valid */
|
||||
u_int8_t sk_specific2; /* sense key specific */
|
||||
u_int8_t sk_specific3; /* sense key Specific */
|
||||
u_int8_t pad[2]; /* padding */
|
||||
};
|
||||
|
||||
struct ast_softc {
|
||||
struct atapi_softc *atp; /* Controller structure */
|
||||
int32_t lun; /* Logical device unit */
|
||||
int32_t flags; /* Device state flags */
|
||||
int32_t blksize; /* Block size (512 | 1024) */
|
||||
struct buf_queue_head buf_queue; /* Queue of i/o requests */
|
||||
struct atapi_params *param; /* Drive parameters table */
|
||||
struct atapi_softc *atp; /* controller structure */
|
||||
int32_t lun; /* logical device unit */
|
||||
int32_t flags; /* device state flags */
|
||||
int32_t blksize; /* block size (512 | 1024) */
|
||||
struct buf_queue_head buf_queue; /* queue of i/o requests */
|
||||
struct atapi_params *param; /* drive parameters table */
|
||||
struct ast_header header; /* MODE SENSE param header */
|
||||
struct ast_cappage cap; /* Capabilities page info */
|
||||
struct ast_cappage cap; /* capabilities page info */
|
||||
struct devstat stats; /* devstat entry */
|
||||
#ifdef DEVFS
|
||||
void *cdevs;
|
||||
void *bdevs;
|
||||
void *cdevs_token;
|
||||
void *bdevs_token;
|
||||
#endif
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user