Make the ATA driver compile & work on the sparc64 platform.

Initial work & code by tmm.

Lots of changes and rearrangements by yours truely to make busdma
be a little less a PITA (but I still dont like it).
This commit is contained in:
Søren Schmidt 2002-04-05 13:13:56 +00:00
parent e8a0928f7e
commit 7800211b08
13 changed files with 658 additions and 340 deletions

View file

@ -249,6 +249,7 @@ ata_detach(device_t dev)
ch->device[MASTER].mode = ATA_PIO;
ch->device[SLAVE].mode = ATA_PIO;
ch->devices = 0;
ata_dmafreetags(ch);
bus_teardown_intr(dev, ch->r_irq, ch->ih);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
@ -1251,7 +1252,7 @@ ata_change_mode(struct ata_device *atadev, int mode)
}
ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE);
ata_dmainit(atadev->channel, atadev->unit, pmode, wmode, umode);
ata_dmainit(atadev, pmode, wmode, umode);
ATA_UNLOCK_CH(atadev->channel);
ata_start(atadev->channel); /* XXX SOS */
}

View file

@ -158,6 +158,18 @@ struct ata_dmaentry {
u_int32_t count;
};
struct ata_dmastate {
bus_dma_tag_t ddmatag; /* data DMA tag */
bus_dmamap_t ddmamap; /* data DMA map */
bus_dma_tag_t cdmatag; /* control DMA tag */
bus_dmamap_t cdmamap; /* control DMA map */
struct ata_dmaentry *dmatab; /* DMA transfer table */
bus_addr_t mdmatab; /* bus address of dmatab */
int flags; /* debugging */
#define ATA_DS_ACTIVE 0x01 /* debugging */
#define ATA_DS_READ 0x02 /* transaction is a read */
};
/* structure describing an ATA/ATAPI device */
struct ata_device {
struct ata_channel *channel;
@ -176,6 +188,7 @@ struct ata_device {
int mode; /* transfermode */
int cmd; /* last cmd executed */
void *result; /* misc data */
struct ata_dmastate dmastate; /* dma state */
};
/* structure describing an ATA channel */
@ -185,6 +198,7 @@ struct ata_channel {
struct resource *r_io; /* io addr resource handle */
struct resource *r_altio; /* altio addr resource handle */
struct resource *r_bmio; /* bmio addr resource handle */
bus_dma_tag_t dmatag; /* parent dma tag */
struct resource *r_irq; /* interrupt of this channel */
void *ih; /* interrupt handle */
int (*intr_func)(struct ata_channel *); /* interrupt function */
@ -259,12 +273,14 @@ int ata_wmode(struct ata_params *);
int ata_umode(struct ata_params *);
int ata_find_dev(device_t, u_int32_t, u_int32_t);
void *ata_dmaalloc(struct ata_channel *, int);
void ata_dmainit(struct ata_channel *, int, int, int, int);
int ata_dmasetup(struct ata_channel *, int, struct ata_dmaentry *, caddr_t, int);
void ata_dmastart(struct ata_channel *, int, struct ata_dmaentry *, int);
int ata_dmaalloc(struct ata_device *);
void ata_dmafree(struct ata_device *);
void ata_dmafreetags(struct ata_channel *);
void ata_dmainit(struct ata_device *, int, int, int);
int ata_dmasetup(struct ata_device *, caddr_t, int32_t);
void ata_dmastart(struct ata_device *, int);
int ata_dmastatus(struct ata_channel *);
int ata_dmadone(struct ata_channel *);
int ata_dmadone(struct ata_device *);
/* macros for locking a channel */
#define ATA_LOCK_CH(ch, value)\
@ -294,10 +310,18 @@ int ata_dmadone(struct ata_channel *);
bus_space_read_multi_2(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_INSW_STRM(res, offset, addr, count) \
bus_space_read_multi_stream_2(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_INSL(res, offset, addr, count) \
bus_space_read_multi_4(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_INSL_STRM(res, offset, addr, count) \
bus_space_read_multi_stream_4(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTB(res, offset, value) \
bus_space_write_1(rman_get_bustag((res)), \
rman_get_bushandle((res)), (offset), (value))
@ -311,7 +335,15 @@ int ata_dmadone(struct ata_channel *);
bus_space_write_multi_2(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTSW_STRM(res, offset, addr, count) \
bus_space_write_multi_stream_2(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTSL(res, offset, addr, count) \
bus_space_write_multi_4(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))
#define ATA_OUTSL_STRM(res, offset, addr, count) \
bus_space_write_multi_stream_4(rman_get_bustag((res)), \
rman_get_bushandle((res)), \
(offset), (addr), (count))

View file

@ -106,6 +106,8 @@ ad_attach(struct ata_device *atadev)
{
struct ad_softc *adp;
dev_t dev;
u_int32_t lbasize;
u_int64_t lbasize48;
if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
ata_prtdev(atadev, "failed to allocate driver storage\n");
@ -123,20 +125,26 @@ ad_attach(struct ata_device *atadev)
adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors;
bioq_init(&adp->queue);
lbasize = (u_int32_t)atadev->param->lba_size_lo |
((u_int32_t)atadev->param->lba_size_hi << 16);
/* does this device need oldstyle CHS addressing */
if (!ad_version(atadev->param->version_major) ||
!(atadev->param->atavalid & ATA_FLAG_54_58) || !atadev->param->lba_size)
!(atadev->param->atavalid & ATA_FLAG_54_58) || !lbasize)
adp->flags |= AD_F_CHS_USED;
/* use the 28bit LBA size if valid */
if (atadev->param->cylinders == 16383 &&
adp->total_secs < atadev->param->lba_size)
adp->total_secs = atadev->param->lba_size;
if (atadev->param->cylinders == 16383 && adp->total_secs < lbasize)
adp->total_secs = lbasize;
lbasize48 = (u_int64_t)atadev->param->lba_size48_1 |
((u_int64_t)atadev->param->lba_size48_2 << 16) |
((u_int64_t)atadev->param->lba_size48_3 << 32) |
((u_int64_t)atadev->param->lba_size48_4 << 48);
/* use the 48bit LBA size if valid */
if (atadev->param->support.address48 &&
atadev->param->lba_size48 > 268435455)
adp->total_secs = atadev->param->lba_size48;
if (atadev->param->support.address48 && lbasize48 > 268435455)
adp->total_secs = lbasize48;
ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL);
/* use multiple sectors/interrupt if device supports it */
@ -168,11 +176,10 @@ ad_attach(struct ata_device *atadev)
/* use DMA if allowed and if drive/controller supports it */
if (ata_dma)
ata_dmainit(atadev->channel, atadev->unit, ata_pmode(atadev->param),
ata_dmainit(atadev, ata_pmode(atadev->param),
ata_wmode(atadev->param), ata_umode(atadev->param));
else
ata_dmainit(atadev->channel, atadev->unit,
ata_pmode(atadev->param), -1, -1);
ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1);
/* use tagged queueing if allowed and supported */
if (ata_tags && ad_tagsupported(adp)) {
@ -235,6 +242,7 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */
biofinish(request->bp, NULL, ENXIO);
ad_free(request);
}
ata_dmafree(atadev);
while ((bp = bioq_first(&adp->queue))) {
bioq_remove(&adp->queue, bp);
biofinish(bp, NULL, ENXIO);
@ -366,7 +374,7 @@ ad_start(struct ata_device *atadev)
if (bp->bio_cmd == BIO_READ)
request->flags |= ADR_F_READ;
if (adp->device->mode >= ATA_DMA) {
if (!(request->dmatab = ata_dmaalloc(atadev->channel, atadev->unit)))
if (ata_dmaalloc(atadev))
adp->device->mode = ATA_PIO;
}
@ -430,8 +438,7 @@ ad_transfer(struct ad_request *request)
/* does this drive & transfer work with DMA ? */
request->flags &= ~ADR_F_DMA_USED;
if (adp->device->mode >= ATA_DMA &&
!ata_dmasetup(adp->device->channel, adp->device->unit,
request->dmatab, request->data, request->bytecount)) {
!ata_dmasetup(adp->device, request->data, request->bytecount)) {
request->flags |= ADR_F_DMA_USED;
request->currentsize = request->bytecount;
@ -480,8 +487,7 @@ ad_transfer(struct ad_request *request)
}
/* start transfer, return and wait for interrupt */
ata_dmastart(adp->device->channel, adp->device->unit,
request->dmatab, request->flags & ADR_F_READ);
ata_dmastart(adp->device, request->flags & ADR_F_READ);
return ATA_OP_CONTINUES;
}
@ -514,13 +520,13 @@ ad_transfer(struct ad_request *request)
/* output the data */
if (adp->device->channel->flags & ATA_USE_16BIT)
ATA_OUTSW(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
ATA_OUTSW_STRM(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
else
ATA_OUTSL(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int32_t));
ATA_OUTSL_STRM(adp->device->channel->r_io, ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int32_t));
return ATA_OP_CONTINUES;
transfer_failed:
@ -551,7 +557,7 @@ ad_interrupt(struct ad_request *request)
/* finish DMA transfer */
if (request->flags & ADR_F_DMA_USED)
dma_stat = ata_dmadone(adp->device->channel);
dma_stat = ata_dmadone(adp->device);
/* do we have a corrected soft error ? */
if (adp->device->channel->status & ATA_S_CORR)
@ -578,8 +584,7 @@ ad_interrupt(struct ad_request *request)
if (request->retries++ < AD_MAX_RETRIES)
printf(" retrying\n");
else {
ata_dmainit(adp->device->channel, adp->device->unit,
ata_pmode(adp->device->param), -1, -1);
ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
printf(" falling back to PIO mode\n");
}
TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain);
@ -590,8 +595,7 @@ ad_interrupt(struct ad_request *request)
if (request->flags & ADR_F_DMA_USED) {
untimeout((timeout_t *)ad_timeout, request,request->timeout_handle);
ad_invalidatequeue(adp, request);
ata_dmainit(adp->device->channel, adp->device->unit,
ata_pmode(adp->device->param), -1, -1);
ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
request->flags |= ADR_F_FORCE_PIO;
printf(" trying PIO mode\n");
TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain);
@ -623,13 +627,15 @@ ad_interrupt(struct ad_request *request)
else {
/* data ready, read in */
if (adp->device->channel->flags & ATA_USE_16BIT)
ATA_INSW(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
ATA_INSW_STRM(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data +
request->donecount), request->currentsize /
sizeof(int16_t));
else
ATA_INSL(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int32_t));
ATA_INSL_STRM(adp->device->channel->r_io, ATA_DATA,
(void*)((uintptr_t)request->data +
request->donecount), request->currentsize /
sizeof(int32_t));
}
}
@ -743,8 +749,7 @@ ad_service(struct ad_softc *adp, int change)
ad_invalidatequeue(adp, NULL);
return ATA_OP_FINISHED;
}
ata_dmastart(adp->device->channel, adp->device->unit,
request->dmatab, request->flags & ADR_F_READ);
ata_dmastart(adp->device, request->flags & ADR_F_READ);
return ATA_OP_CONTINUES;
}
return ATA_OP_FINISHED;
@ -753,8 +758,6 @@ ad_service(struct ad_softc *adp, int change)
static void
ad_free(struct ad_request *request)
{
if (request->dmatab)
free(request->dmatab, M_DEVBUF);
request->softc->tags[request->tag] = NULL;
free(request, M_AD);
}
@ -829,11 +832,10 @@ ad_timeout(struct ad_request *request)
request->tag, request->serv);
if (request->flags & ADR_F_DMA_USED) {
ata_dmadone(adp->device->channel);
ata_dmadone(adp->device);
ad_invalidatequeue(adp, request);
if (request->retries == AD_MAX_RETRIES) {
ata_dmainit(adp->device->channel, adp->device->unit,
ata_pmode(adp->device->param), -1, -1);
ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1);
ata_prtdev(adp->device, "trying fallback to PIO mode\n");
request->retries = 0;
}
@ -863,13 +865,11 @@ ad_reinit(struct ata_device *atadev)
ata_command(atadev, ATA_C_SET_MULTI, 0,
adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY);
if (adp->device->mode >= ATA_DMA)
ata_dmainit(atadev->channel, atadev->unit,
ata_pmode(adp->device->param),
ata_dmainit(atadev, ata_pmode(adp->device->param),
ata_wmode(adp->device->param),
ata_umode(adp->device->param));
else
ata_dmainit(atadev->channel, atadev->unit,
ata_pmode(adp->device->param), -1, -1);
ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1);
}
void

View file

@ -48,7 +48,6 @@ struct ad_request {
struct bio *bp; /* associated bio ptr */
u_int8_t tag; /* tag ID of this request */
int serv; /* request had service */
struct ata_dmaentry *dmatab; /* DMA transfer table */
TAILQ_ENTRY(ad_request) chain; /* list management */
};

File diff suppressed because it is too large Load diff

View file

@ -107,33 +107,40 @@ DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0);
*/
#include "pci.h"
#if NPCI == 0
void *
ata_dmaalloc(struct ata_channel *ch, int device)
int
ata_dmaalloc(struct ata_device *atadev)
{
return 0;
return ENXIO;
}
void
ata_dmainit(struct ata_channel *ch, int device,
int piomode, int wdmamode, int udmamode)
ata_dmafree(struct ata_device *atadev)
{
}
void
ata_dmafreetags(struct ata_channel *ch)
{
}
void
ata_dmainit(struct ata_device *atadev, int piomode, int wdmamode, int udmamode)
{
}
int
ata_dmasetup(struct ata_channel *ch, int device, struct ata_dmaentry *dmatab,
caddr_t data, int32_t count)
ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count)
{
return -1;
}
void
ata_dmastart(struct ata_channel *ch, int device,
struct ata_dmaentry *dmatab, int dir)
ata_dmastart(struct ata_device *atadev, int dir)
{
}
int
ata_dmadone(struct ata_channel *ch)
ata_dmadone(struct ata_device *atadev)
{
return -1;
}

View file

@ -28,6 +28,7 @@
* $FreeBSD$
*/
#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@ -363,13 +364,19 @@ ata_pci_attach(device_t dev)
type = pci_get_devid(dev);
class = pci_get_class(dev);
subclass = pci_get_subclass(dev);
cmd = pci_read_config(dev, PCIR_COMMAND, 4);
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
if (!(cmd & PCIM_CMD_PORTEN)) {
device_printf(dev, "ATA channel disabled by BIOS\n");
return 0;
}
#ifdef ATA_ENABLE_BUSMASTER
if (!(cmd & PCIM_CMD_BUSMASTEREN)) {
pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2);
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
}
#endif
/* is busmastering supported ? */
if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) ==
(PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) {
@ -403,22 +410,28 @@ ata_pci_attach(device_t dev)
break;
case 0x00041103: /* HighPoint HPT366/368/370/372 default setup */
if (pci_get_revid(dev) < 2) { /* HPT 366 */
if (pci_get_revid(dev) < 2) { /* HPT366 */
/* turn off interrupt prediction */
pci_write_config(dev, 0x51,
(pci_read_config(dev, 0x51, 1) & ~0x80), 1);
break;
}
/* turn off interrupt prediction */
pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1);
pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1);
if (pci_get_revid(dev) < 5) { /* HPT368/370 */
/* turn off interrupt prediction */
pci_write_config(dev, 0x51,
(pci_read_config(dev, 0x51, 1) & ~0x03), 1);
pci_write_config(dev, 0x55,
(pci_read_config(dev, 0x55, 1) & ~0x03), 1);
/* turn on interrupts */
pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
/* turn on interrupts */
pci_write_config(dev, 0x5a,
(pci_read_config(dev, 0x5a, 1) & ~0x10), 1);
/* set clocks etc */
pci_write_config(dev, 0x5b, 0x22, 1);
break;
/* set clocks etc */
pci_write_config(dev, 0x5b, 0x22, 1);
break;
}
/* FALLTHROUGH */
case 0x00051103: /* HighPoint HPT372 default setup */
case 0x00081103: /* HighPoint HPT374 default setup */
@ -481,6 +494,10 @@ ata_pci_attach(device_t dev)
(pci_get_revid(dev) >= 0x92) ? 0x03 : 0x02, 1);
break;
case 0x06461095: /* CMD 646 enable interrupts, set DMA read mode */
pci_write_config(dev, 0x71, 0x01, 1);
break;
case 0x10001042: /* RZ 100? known bad, no DMA */
case 0x10011042:
case 0x06401095: /* CMD 640 known bad, no DMA */
@ -631,7 +648,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
start, end, count, flags);
if (res) {
start = rman_get_start(res) + 2;
end = rman_get_start(res) + ATA_ALTIOSIZE - 1;
end = start + ATA_ALTIOSIZE - 1;
count = ATA_ALTIOSIZE;
BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
SYS_RES_IOPORT, myrid, res);

View file

@ -74,7 +74,7 @@ atapi_attach(struct ata_device *atadev)
ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL);
if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) {
ata_dmainit(atadev->channel, atadev->unit,
ata_dmainit(atadev,
(ata_pmode(atadev->param) < 0) ?
(atadev->param->support_dma ? 4:0):ata_pmode(atadev->param),
(ata_wmode(atadev->param) < 0) ?
@ -82,7 +82,7 @@ atapi_attach(struct ata_device *atadev)
ata_umode(atadev->param));
}
else
ata_dmainit(atadev->channel, atadev->unit,
ata_dmainit(atadev,
ata_pmode(atadev->param) < 0 ? 0 : ata_pmode(atadev->param),
-1, -1);
ATA_UNLOCK_CH(atadev->channel);
@ -152,10 +152,9 @@ atapi_detach(struct ata_device *atadev)
struct bio *bp = (struct bio *) request->driver;
biofinish(bp, NULL, ENXIO);
}
if (request->dmatab)
free(request->dmatab, M_DEVBUF);
free(request, M_ATAPI);
}
ata_dmafree(atadev);
free(atadev->result, M_ATAPI);
atadev->driver = NULL;
atadev->flags = 0;
@ -186,7 +185,7 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data,
request->driver = driver;
}
if (atadev->mode >= ATA_DMA) {
if (!(request->dmatab = ata_dmaalloc(atadev->channel, atadev->unit)))
if (ata_dmaalloc(atadev))
atadev->mode = ATA_PIO;
}
@ -212,8 +211,6 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data,
error = request->error;
if (error)
bcopy(&request->sense, atadev->result, sizeof(struct atapi_reqsense));
if (request->dmatab)
free(request->dmatab, M_DEVBUF);
free(request, M_ATAPI);
return error;
}
@ -279,8 +276,7 @@ atapi_transfer(struct atapi_request *request)
((request->ccb[0] == ATAPI_WRITE ||
request->ccb[0] == ATAPI_WRITE_BIG) &&
!(atadev->channel->flags & ATA_ATAPI_DMA_RO))) &&
!ata_dmasetup(atadev->channel, atadev->unit, request->dmatab,
(void *)request->data, request->bytecount)) {
!ata_dmasetup(atadev, (void *)request->data, request->bytecount)) {
request->flags |= ATPR_F_DMA_USED;
}
@ -291,8 +287,7 @@ atapi_transfer(struct atapi_request *request)
ata_prtdev(atadev, "failure to send ATAPI packet command\n");
if (request->flags & ATPR_F_DMA_USED)
ata_dmastart(atadev->channel, atadev->unit,
request->dmatab, request->flags & ATPR_F_READ);
ata_dmastart(atadev, request->flags & ATPR_F_READ);
/* command interrupt device ? just return */
if (atadev->param->drq_type == ATAPI_DRQT_INTR)
@ -320,8 +315,8 @@ atapi_transfer(struct atapi_request *request)
DELAY(10);
/* send actual command */
ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb,
request->ccbsize / sizeof(int16_t));
ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb,
request->ccbsize / sizeof(int16_t));
return ATA_OP_CONTINUES;
}
@ -343,13 +338,13 @@ atapi_interrupt(struct atapi_request *request)
atapi_finish(request);
return ATA_OP_FINISHED;
}
ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb,
request->ccbsize / sizeof(int16_t));
ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb,
request->ccbsize / sizeof(int16_t));
return ATA_OP_CONTINUES;
}
if (request->flags & ATPR_F_DMA_USED) {
dma_stat = ata_dmadone(atadev->channel);
dma_stat = ata_dmadone(atadev);
if ((atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) ||
dma_stat & ATA_BMSTAT_ERROR) {
request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR);
@ -471,14 +466,14 @@ atapi_reinit(struct ata_device *atadev)
{
/* reinit device parameters */
if (atadev->mode >= ATA_DMA)
ata_dmainit(atadev->channel, atadev->unit,
ata_dmainit(atadev,
(ata_pmode(atadev->param) < 0) ?
(atadev->param->support_dma ? 4:0):ata_pmode(atadev->param),
(ata_wmode(atadev->param) < 0) ?
(atadev->param->support_dma ? 2:0):ata_wmode(atadev->param),
ata_umode(atadev->param));
else
ata_dmainit(atadev->channel, atadev->unit,
ata_dmainit(atadev,
ata_pmode(atadev->param)<0 ? 0 : ata_pmode(atadev->param),
-1, -1);
}
@ -533,11 +528,11 @@ atapi_read(struct atapi_request *request, int length)
*buffer = (int8_t *)&request->sense;
if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)))
ATA_INSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int16_t));
ATA_INSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int16_t));
else
ATA_INSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int32_t));
ATA_INSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int32_t));
if (request->bytecount < length) {
ata_prtdev(request->device, "read data overrun %d/%d\n",
@ -562,11 +557,11 @@ atapi_write(struct atapi_request *request, int length)
*buffer = (int8_t *)&request->sense;
if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t)))
ATA_OUTSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int16_t));
ATA_OUTSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int16_t));
else
ATA_OUTSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int32_t));
ATA_OUTSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer),
size / sizeof(int32_t));
if (request->bytecount < length) {
ata_prtdev(request->device, "write data underrun %d/%d\n",
@ -588,11 +583,8 @@ atapi_finish(struct atapi_request *request)
atapi_cmd2str(request->ccb[0]));
#endif
if (request->callback) {
if (!((request->callback)(request))) {
if (request->dmatab)
free(request->dmatab, M_DEVBUF);
if (!((request->callback)(request)))
free(request, M_ATAPI);
}
}
else
wakeup((caddr_t)request);
@ -608,9 +600,9 @@ atapi_timeout(struct atapi_request *request)
atapi_cmd2str(request->ccb[0]));
if (request->flags & ATPR_F_DMA_USED) {
ata_dmadone(atadev->channel);
ata_dmadone(atadev);
if (request->retries == ATAPI_MAX_RETRIES) {
ata_dmainit(atadev->channel, atadev->unit,
ata_dmainit(atadev,
(ata_pmode(atadev->param) < 0) ? 0 :
ata_pmode(atadev->param), -1, -1);
ata_prtdev(atadev, "trying fallback to PIO mode\n");

View file

@ -166,7 +166,6 @@ struct atapi_request {
caddr_t data; /* pointer to data buf */
atapi_callback_t *callback; /* ptr to callback func */
struct ata_dmaentry *dmatab; /* DMA transfer table */
void *driver; /* driver specific */
TAILQ_ENTRY(atapi_request) chain; /* list management */
};

View file

@ -45,6 +45,7 @@
#include <sys/fcntl.h>
#include <sys/conf.h>
#include <sys/ctype.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-cd.h>
@ -223,6 +224,7 @@ acddetach(struct ata_device *atadev)
free(entry, M_ACD);
}
destroy_dev(cdp->dev);
EVENTHANDLER_DEREGISTER(dev_clone, cdp->clone_evh);
devstat_remove_entry(cdp->stats);
free(cdp->stats, M_ACD);
ata_free_name(atadev);
@ -253,6 +255,28 @@ acd_init_lun(struct ata_device *atadev)
return cdp;
}
/*
* Handle dev_clone events, so that acd can be used as root device.
*/
static void
acd_clone(void *arg, char *name, int namelen, dev_t *dev)
{
struct acd_softc *cdp;
char *p;
int unit;
cdp = arg;
if (*dev != NODEV)
return;
if (!dev_stdclone(name, &p, "acd", &unit))
return;
/* Handle compatability slices. */
if (*p != '\0' && strcmp(p, "a") != 0 && strcmp(p, "c") != 0)
return;
if (unit == cdp->lun)
*dev = makedev(acd_cdevsw.d_maj, dkmakeminor(cdp->lun, 0, 0));
}
static void
acd_make_dev(struct acd_softc *cdp)
{
@ -267,6 +291,7 @@ acd_make_dev(struct acd_softc *cdp)
dev->si_bsize_phys = 2048; /* XXX SOS */
cdp->dev = dev;
cdp->device->flags |= ATA_D_MEDIA_CHANGED;
cdp->clone_evh = EVENTHANDLER_REGISTER(dev_clone, acd_clone, cdp, 1000);
}
static void

View file

@ -76,11 +76,6 @@ struct audiopage {
} port[4];
};
/* CDROM Capabilities and Mechanical Status Page */
struct cappage {
/* mode page data header */
u_int16_t data_length;
u_int8_t medium_type;
#define MST_TYPE_MASK_LOW 0x0f
#define MST_FMT_NONE 0x00
#define MST_DATA_120 0x01
@ -101,15 +96,35 @@ struct cappage {
#define MST_DOOR_OPEN 0x71
#define MST_FMT_ERROR 0x72
#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
#define MST_DLEN_32 0
#define MST_DLEN_16 1
#define MST_DLEN_24 2
#define MST_DLEN_24_I2S 3
#define ATAPI_CDROM_CAP_PAGE 0x2a
/* CDROM Capabilities and Mechanical Status Page */
struct cappage {
/* mode page data header */
u_int16_t data_length;
u_int8_t medium_type;
u_int8_t dev_spec;
u_int8_t unused[2];
u_int16_t blk_desc_len;
/* capabilities page */
u_int8_t page_code;
#define ATAPI_CDROM_CAP_PAGE 0x2a
u_int8_t param_len;
#if BYTE_ORDER == LITTLE_ENDIAN
u_int8_t read_cdr :1; /* supports CD-R read */
u_int8_t read_cdrw :1; /* supports CD-RW read */
u_int8_t read_packet :1; /* supports reading packet tracks */
@ -117,6 +132,7 @@ struct cappage {
u_int8_t read_dvdr :1; /* supports DVD-R read */
u_int8_t read_dvdram :1; /* supports DVD-RAM read */
u_int8_t reserved2_67 :2;
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 */
@ -124,6 +140,7 @@ struct cappage {
u_int8_t write_dvdr :1; /* supports DVD-R write */
u_int8_t write_dvdram :1; /* supports DVD-RAM write */
u_int8_t reserved3_67 :2;
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 */
@ -132,6 +149,7 @@ struct cappage {
u_int8_t mode2_form2 :1; /* mode 2 form 2 format */
u_int8_t multisession :1; /* multi-session photo-CD */
u_int8_t burnproof :1; /* supports burnproof */
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 */
@ -140,21 +158,64 @@ struct cappage {
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 :1;
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:6;
#else
/* This is read using 16-bit stream transfers */
u_int8_t reserved2_67 :2;
u_int8_t read_dvdram :1; /* supports DVD-RAM read */
u_int8_t read_dvdr :1; /* supports DVD-R read */
u_int8_t read_dvdrom :1; /* supports DVD-ROM read */
u_int8_t read_packet :1; /* supports reading packet tracks */
u_int8_t read_cdrw :1; /* supports CD-RW read */
u_int8_t read_cdr :1; /* supports CD-R read */
u_int8_t reserved3_67 :2;
u_int8_t write_dvdram :1; /* supports DVD-RAM write */
u_int8_t write_dvdr :1; /* supports DVD-R write */
u_int8_t reserved3_3 :1;
u_int8_t test_write :1; /* supports test writing */
u_int8_t write_cdrw :1; /* supports CD-RW write */
u_int8_t write_cdr :1; /* supports CD-R write */
u_int8_t burnproof :1; /* supports burnproof */
u_int8_t multisession :1; /* multi-session photo-CD */
u_int8_t mode2_form2 :1; /* mode 2 form 2 format */
u_int8_t mode2_form1 :1; /* mode 2 form 1 (XA) read */
u_int8_t dport2 :1; /* digital audio on port 2 */
u_int8_t dport1 :1; /* digital audio on port 1 */
u_int8_t composite :1; /* composite audio/video supported */
u_int8_t audio_play :1; /* audio play supported */
u_int8_t :1;
u_int8_t upc :1; /* can return the catalog number UPC */
u_int8_t isrc :1; /* can return the ISRC info */
u_int8_t c2 :1; /* C2 error pointers supported */
u_int8_t rw_corr :1; /* R-W subchannel data corrected */
u_int8_t rw :1; /* combined R-W subchannels */
u_int8_t cd_da_stream :1; /* CD-DA streaming */
u_int8_t cd_da :1; /* audio-CD read supported */
u_int8_t mech :3; /* loading mechanism type */
u_int8_t :1;
u_int8_t eject :1; /* can eject */
u_int8_t prevent :1; /* prevent jumper installed */
u_int8_t locked :1; /* current lock state */
u_int8_t lock :1; /* can be locked */
u_int8_t:6;
u_int8_t sep_mute :1; /* independent mute of channels */
u_int8_t sep_vol :1; /* independent volume of channels */
#endif
u_int16_t max_read_speed; /* max raw data rate in bytes/1000 */
u_int16_t max_vol_levels; /* number of discrete volume levels */
@ -162,40 +223,48 @@ struct cappage {
u_int16_t cur_read_speed; /* current data rate in bytes/1000 */
u_int8_t reserved3;
#if BYTE_ORDER == LITTLE_ENDIAN
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
#define MST_DLEN_24 2
#define MST_DLEN_24_I2S 3
u_int8_t :3;
#else
u_int8_t :3;
u_int8_t dlen :2;
u_int8_t lsbf :1; /* set if LSB first */
u_int8_t rch :1; /* high LRCK indicates left channel */
u_int8_t bckf :1; /* data valid on failing edge of BCK */
#endif
u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */
u_int16_t cur_write_speed; /* current data rate in bytes/1000 */
u_int16_t copy_protect_rev;
u_int16_t reserved4;
};
/* 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 */
#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 reserved0 :5;
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
/* 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 fault :1; /* fault in last operation */
u_int8_t reserved0 :5;
u_int8_t cd_state :3; /* current mechanism state */
u_int8_t current_lba[3]; /* current LBA */
u_int8_t slots; /* number of available slots */
u_int16_t table_length; /* slot table length */
@ -326,4 +395,5 @@ struct acd_softc {
struct disklabel disklabel; /* fake disk label */
struct devstat *stats; /* devstat entry */
dev_t dev; /* device place holders */
eventhandler_tag clone_evh;
};

View file

@ -39,6 +39,7 @@
#include <sys/disk.h>
#include <sys/devicestat.h>
#include <sys/cdio.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-fd.h>

View file

@ -40,6 +40,7 @@
#include <sys/mtio.h>
#include <sys/disklabel.h>
#include <sys/devicestat.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-tape.h>