Support DMA on ATAPI devices (finally).
This makes my system use only ~5% CPU on reading 4.5Mbyte/sec from a CDROM, which before was limitted to 1.8Mbyte/sec due to 100% CPU load..
This commit is contained in:
parent
4368f24089
commit
51df811367
@ -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-all.h,v 1.6 1999/04/18 20:48:15 sos Exp $
|
||||
* $Id: ata-all.h,v 1.7 1999/06/25 09:02:57 sos Exp $
|
||||
*/
|
||||
|
||||
/* ATA register defines */
|
||||
@ -87,12 +87,6 @@
|
||||
#define ATA_OP_FINISHED 0x00
|
||||
#define ATA_OP_CONTINUES 0x01
|
||||
|
||||
/* devices types */
|
||||
#define ATA_ATA_MASTER 0x01
|
||||
#define ATA_ATA_SLAVE 0x02
|
||||
#define ATA_ATAPI_MASTER 0x04
|
||||
#define ATA_ATAPI_SLAVE 0x08
|
||||
|
||||
/* busmaster DMA related defines */
|
||||
#define ATA_BM_OFFSET1 0x08
|
||||
#define ATA_DMA_ENTRIES 256
|
||||
@ -132,6 +126,11 @@ struct ata_softc {
|
||||
struct ata_dmaentry *dmatab[2]; /* DMA transfer tables */
|
||||
int32_t flags; /* controller flags */
|
||||
int32_t devices; /* what is present */
|
||||
#define ATA_ATA_MASTER 0x01
|
||||
#define ATA_ATA_SLAVE 0x02
|
||||
#define ATA_ATAPI_MASTER 0x04
|
||||
#define ATA_ATAPI_SLAVE 0x08
|
||||
|
||||
u_int8_t status; /* last controller status */
|
||||
u_int8_t error; /* last controller error */
|
||||
int32_t active; /* active processing 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/06/25 09:02:59 sos Exp $
|
||||
* $Id: ata-disk.c,v 1.15 1999/07/17 17:55:53 phk Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -540,6 +540,10 @@ ad_transfer(struct ad_request *request)
|
||||
|
||||
/* setup transfer parameters */
|
||||
count = howmany(request->bytecount, DEV_BSIZE);
|
||||
if (count > 256) {
|
||||
count = 256;
|
||||
printf("ad_transfer: count=%d not supported\n", count);
|
||||
}
|
||||
|
||||
if (adp->flags & AD_F_LBA_ENABLED) {
|
||||
sector = (blkno >> 0) & 0xff;
|
||||
@ -745,7 +749,7 @@ ad_drvinit(void)
|
||||
|
||||
if (!ad_devsw_installed) {
|
||||
if (!ad_cdevsw.d_maxio)
|
||||
ad_cdevsw.d_maxio = 254 * DEV_BSIZE;
|
||||
ad_cdevsw.d_maxio = 256 * DEV_BSIZE;
|
||||
cdevsw_add(&ad_cdevsw);
|
||||
fakewd_cdevsw = ad_cdevsw;
|
||||
fakewd_cdevsw.d_maj = 3;
|
||||
|
@ -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-dma.c,v 1.8 1999/05/26 23:01:57 gallatin Exp $
|
||||
* $Id: ata-dma.c,v 1.9 1999/08/06 17:39:38 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -169,6 +169,11 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
|
||||
|
||||
case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */
|
||||
case 0x4d38105a: /* Promise Ultra/66 controllers */
|
||||
/* the promise seems to have trouble with DMA on ATAPI devices */
|
||||
if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
|
||||
(device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
|
||||
break;
|
||||
|
||||
devno = (scp->unit << 1) + (device ? 1 : 0);
|
||||
if (udmamode >=2) {
|
||||
printf("ata%d: %s: setting up UDMA2 mode on Promise chip ",
|
||||
|
@ -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.c,v 1.9 1999/05/20 09:12:04 sos Exp $
|
||||
* $Id: atapi-all.c,v 1.10 1999/06/25 09:03:01 sos Exp $
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
@ -64,6 +64,38 @@ int32_t astattach(struct atapi_softc *);
|
||||
|
||||
static struct intr_config_hook *atapi_attach_hook;
|
||||
|
||||
static __inline int
|
||||
apiomode(struct atapi_params *ap)
|
||||
{
|
||||
if ((ap->atavalid & 2) == 2) {
|
||||
if ((ap->apiomodes & 2) == 2) return 4;
|
||||
if ((ap->apiomodes & 1) == 1) return 3;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
wdmamode(struct atapi_params *ap)
|
||||
{
|
||||
if ((ap->atavalid & 2) == 2) {
|
||||
if ((ap->wdmamodes & 4) == 4) return 2;
|
||||
if ((ap->wdmamodes & 2) == 2) return 1;
|
||||
if ((ap->wdmamodes & 1) == 1) return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
udmamode(struct atapi_params *ap)
|
||||
{
|
||||
if ((ap->atavalid & 4) == 4) {
|
||||
if ((ap->udmamodes & 4) == 4) return 2;
|
||||
if ((ap->udmamodes & 2) == 2) return 1;
|
||||
if ((ap->udmamodes & 1) == 1) return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
atapi_attach(void *notused)
|
||||
{
|
||||
@ -90,6 +122,19 @@ atapi_attach(void *notused)
|
||||
free(atp, M_DEVBUF);
|
||||
continue;
|
||||
}
|
||||
printf("atapi: piomode=%d, dmamode=%d, udmamode=%d\n",
|
||||
apiomode(atp->atapi_parm),
|
||||
wdmamode(atp->atapi_parm),
|
||||
udmamode(atp->atapi_parm));
|
||||
if (!(atp->atapi_parm->drqtype == ATAPI_DRQT_INTR) &&
|
||||
!ata_dmainit(atp->controller, atp->unit,
|
||||
apiomode(atp->atapi_parm),
|
||||
wdmamode(atp->atapi_parm),
|
||||
udmamode(atp->atapi_parm)))
|
||||
atp->flags |= ATAPI_F_DMA_ENABLED;
|
||||
|
||||
printf("atapi: %s transfer mode set\n",
|
||||
(atp->flags & ATAPI_F_DMA_ENABLED) ? "DMA" :"PIO");
|
||||
|
||||
switch (atp->atapi_parm->device_type) {
|
||||
#if NATAPICD > 0
|
||||
@ -240,10 +285,21 @@ atapi_transfer(struct atapi_request *request)
|
||||
#ifdef ATAPI_DEBUG
|
||||
printf("atapi: trying to start %s cmd\n", atapi_cmd2str(request->ccb[0]));
|
||||
#endif
|
||||
/* if DMA enabled setup DMA hardware */
|
||||
atp->flags &= ~ATAPI_F_DMA_USED;
|
||||
if ((request->ccb[0]==ATAPI_READ_BIG || request->ccb[0]==ATAPI_WRITE_BIG) &&
|
||||
(atp->flags & ATAPI_F_DMA_ENABLED) &&
|
||||
!ata_dmasetup(atp->controller, atp->unit,
|
||||
(void *)request->data, request->bytecount,
|
||||
request->flags & A_READ)) {
|
||||
atp->flags |= ATAPI_F_DMA_USED;
|
||||
}
|
||||
|
||||
/* start ATAPI operation */
|
||||
ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD,
|
||||
request->bytecount, 0, 0, 0, 0, ATA_IMMEDIATE);
|
||||
request->bytecount, 0, 0, 0,
|
||||
(atp->flags & ATAPI_F_DMA_USED) ? ATA_F_DMA : 0,
|
||||
ATA_IMMEDIATE);
|
||||
|
||||
/* command interrupt device ? just return */
|
||||
if (atp->atapi_parm->drqtype == ATAPI_DRQT_INTR)
|
||||
@ -268,6 +324,9 @@ atapi_transfer(struct atapi_request *request)
|
||||
/* this seems to be needed for some (slow) devices */
|
||||
DELAY(10);
|
||||
|
||||
if (atp->flags & ATAPI_F_DMA_USED)
|
||||
ata_dmastart(atp->controller, atp->unit);
|
||||
|
||||
/* send actual command */
|
||||
outsw(atp->controller->ioaddr + ATA_DATA, request->ccb,
|
||||
request->ccbsize / sizeof(int16_t));
|
||||
@ -277,7 +336,7 @@ int32_t
|
||||
atapi_interrupt(struct atapi_request *request)
|
||||
{
|
||||
struct atapi_softc *atp;
|
||||
int32_t length, reason, resid;
|
||||
int32_t length, reason, resid, dma_stat = 0;
|
||||
|
||||
#ifdef ATAPI_DEBUG
|
||||
printf("atapi_interrupt: enter\n");
|
||||
@ -285,6 +344,9 @@ printf("atapi_interrupt: enter\n");
|
||||
/* get device params */
|
||||
atp = request->device;
|
||||
|
||||
if (atp->flags & ATAPI_F_DMA_USED)
|
||||
dma_stat = ata_dmadone(atp->controller, atp->unit);
|
||||
|
||||
/* get drive status */
|
||||
if (atapi_wait(atp, 0) < 0) {
|
||||
printf("atapi_interrupt: timeout waiting for status");
|
||||
@ -304,6 +366,21 @@ printf("atapi_interrupt: enter\n");
|
||||
printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason);
|
||||
#endif
|
||||
|
||||
if (atp->flags & ATAPI_F_DMA_USED) {
|
||||
if (atp->controller->status & (ATA_S_ERROR | ATA_S_DWF) &&
|
||||
dma_stat != ATA_BMSTAT_INTERRUPT)
|
||||
request->result = atp->controller->error;
|
||||
else {
|
||||
request->donecount = request->bytecount;
|
||||
request->bytecount = 0;
|
||||
request->result = 0;
|
||||
}
|
||||
TAILQ_REMOVE(&atp->controller->atapi_queue, request, chain);
|
||||
atp->flags &= ~ATAPI_F_DMA_USED;
|
||||
wakeup((caddr_t)request);
|
||||
return ATA_OP_FINISHED;
|
||||
}
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case ATAPI_P_CMDOUT:
|
||||
|
Loading…
Reference in New Issue
Block a user