Fourth update to the new ATA/ATAPI driver:

Well, better late than newer, but things has been hectic
around here, sorry for the long delay.

DMA support has been added to the ATA disk driver.
This only works on Intel PIIX3/4, Acer Aladdin and Promise controllers.
The promise support works without the BIOS on the board,
and timing modes are set to support up to UDMA speed. This
solves the problems with having more than one promise controller
in the same system.
There is support for "generic" DMA, that might work on other
controllers, but now you have been warned :)
More chipset specific code will come soon, I have to find testers
with the approbiate HW, more on that when I have it ready.

The system now uses its own major numbers, please run MAKEDEV
with the devices you need (ad?, acd?, afd?, ast?).
For now the disk driver will also attach to the old wd major
so one can at least boot without this step, but be warned, this
will eventually go away. The bootblocks will have to be changed
before one can boot directly from an "ad" device though.

Fixed problems:

    All known hang problems should be solved
	The probe code has been sligthly changed, this should solve
	the reports I have lying around (I hope).

    Hangs when accessing ata & atapi device on the same channel simultaniously.
	A real braino in ata_start caused this, fixed.

As usual USE AT YOUR OWN RISK!!, this is still pre alpha level code.
Especially the DMA support can hose your disk real bad if anything
goes wrong, agaiin you have been warned :)

But please tell me how it works for you!

Enjoy!

-Søren
This commit is contained in:
sos 1999-03-28 18:57:20 +00:00
parent 6fdf96baf6
commit cc8db63d86
12 changed files with 852 additions and 234 deletions

View File

@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
# $Id: files.i386,v 1.228 1999/03/10 10:36:29 yokota Exp $
# $Id: files.i386,v 1.229 1999/03/16 13:34:02 sos Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -35,6 +35,7 @@ ukbdmap.h optional ukbd_dflt_keymap \
clean "ukbdmap.h"
#
dev/ata/ata-all.c optional ata device-driver
dev/ata/ata-dma.c optional ata device-driver
dev/ata/atapi-all.c optional ata device-driver
dev/ata/ata-disk.c optional atadisk device-driver
dev/ata/atapi-cd.c optional atapicd device-driver

View File

@ -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.c,v 1.3 1999/03/05 09:43:30 sos Exp $
* $Id: ata-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
#include "ata.h"
@ -41,7 +41,10 @@
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/devicestat.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/clock.h>
#include <machine/smp.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <i386/isa/icu.h>
@ -53,6 +56,10 @@
/* misc defines */
#define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */
#define MIN(a,b) ((a)>(b)?(b):(a))
#if NSMP == 0
#define isa_apic_irq(x) x
#endif
/* prototypes */
#if NISA > 0
@ -64,7 +71,7 @@ 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_probe(int32_t, int32_t, int32_t, pcici_t, int32_t *);
static void ataintr(int32_t);
static int32_t atanlun = 0, sysctrl = 0;
@ -84,7 +91,8 @@ ata_isaprobe(struct isa_device *devp)
return 0;
}
}
res=ata_probe(devp->id_iobase, devp->id_iobase+ATA_ALTPORT, &devp->id_unit);
res = ata_probe(devp->id_iobase, devp->id_iobase + ATA_ALTPORT, 0, 0,
&devp->id_unit);
if (res)
devp->id_intr = (inthand2_t *)ataintr;
return res;
@ -115,20 +123,22 @@ ata_pciprobe(pcici_t tag, pcidi_t type)
((data & PCI_SUBCLASS_MASK) == 0x00010000 ||
((data & PCI_SUBCLASS_MASK) == 0x00040000))) {
switch (type) {
case 0x71118086:
return "Intel PIIX4 IDE controller";
case 0x70108086:
return "Intel PIIX3 IDE controller";
case 0x12308086:
return "Intel PIIX IDE controller";
case 0x70108086:
return "Intel PIIX3 IDE controller";
case 0x71118086:
return "Intel PIIX4 IDE controller";
case 0x4d33105a:
return "Promise Ultra/33 IDE controller";
case 0x522910b9:
return "AcerLabs Aladdin IDE controller";
#if 0
case 0x05711106:
return "VIA Apollo IDE controller";
case 0x01021078:
return "Cyrix 5530 IDE controller";
case 0x522910b9:
return "Acer Aladdin IV/V IDE controller";
#endif
default:
return "Unknown PCI IDE controller";
}
@ -140,7 +150,8 @@ static void
ata_pciattach(pcici_t tag, int32_t unit)
{
pcidi_t type, class, cmd;
int32_t iobase_1, iobase_2, altiobase_1, altiobase_2, irq1, irq2;
int32_t iobase_1, iobase_2, altiobase_1, altiobase_2;
int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2;
int32_t lun;
/* set up vendor-specific stuff */
@ -149,39 +160,22 @@ ata_pciattach(pcici_t tag, int32_t unit)
cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
#ifdef ATA_DEBUG
printf("ata: type=%08x class=%08x cmd=%08x\n", type, class, cmd);
printf("ata%d: type=%08x class=%08x cmd=%08x\n", unit, type, class, cmd);
#endif
switch (type) {
case 0x71118086:
case 0x70108086:
case 0x12308086: /* Intel PIIX, PIIX3, PIIX4 */
break;
case 0x05711106: /* VIA Apollo chipset family */
break;
case 0x4d33105a: /* Promise controllers */
break;
case 0x01021078: /* Cyrix 5530 */
break;
case 0x522910B9: /* Acer Aladdin IV/V (M5229) */
break;
default:
/* everybody else */
break;
}
if (type == 0x4d33105a) { /* the Promise is special */
/* if this is at Promise controller handle it specially */
if (type == 0x4d33105a) {
iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc;
altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc;
iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc;
altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
irq1 = irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc;
bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
sysctrl = (pci_conf_read(tag, 0x20) & 0xfffc) + 0x1c;
printf("ata-pci%d: Busmastering DMA supported\n", unit);
}
/* everybody else seems to do it this way */
else {
if ((class & 0x100) == 0) {
iobase_1 = IO_WD1;
@ -203,12 +197,32 @@ ata_pciattach(pcici_t tag, int32_t unit)
altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc;
irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff;
}
/* is this controller busmaster capable ? */
if (pci_conf_read(tag, PCI_CLASS_REG) & 0x8000) {
/* is busmastering support turned on ? */
if ((pci_conf_read(tag, PCI_COMMAND_STATUS_REG) & 5) == 5) {
/* is there a valid port range to connect to ? */
if ((bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc)) {
bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
printf("ata-pci%d: Busmastering DMA supported\n", unit);
}
else
printf("ata-pci%d: Busmastering DMA not configured\n",unit);
}
else
printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
}
else
printf("ata-pci%d: Busmastering DMA not supported\n", unit);
}
/* now probe the addresse found for "real" ATA/ATAPI hardware */
if (ata_probe(iobase_1, altiobase_1, &lun)) {
lun = 0;
if (ata_probe(iobase_1, altiobase_1, bmaddr_1, tag, &lun)) {
if (iobase_1 == IO_WD1)
register_intr(irq1, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun);
register_intr(irq1, (int)"", 0, (inthand2_t *)ataintr,
&bio_imask, lun);
else {
if (sysctrl)
pci_map_int(tag, (inthand2_t *)promise_intr,
@ -217,17 +231,19 @@ ata_pciattach(pcici_t tag, int32_t unit)
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);
lun, iobase_1, isa_apic_irq(irq1), unit);
}
if (ata_probe(iobase_2, altiobase_2, &lun)) {
lun = 1;
if (ata_probe(iobase_2, altiobase_2, bmaddr_2, tag, &lun)) {
if (iobase_2 == IO_WD2)
register_intr(irq2, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun);
register_intr(irq2, (int)"", 0, (inthand2_t *)ataintr,
&bio_imask, lun);
else {
if (!sysctrl)
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);
lun, iobase_2, isa_apic_irq(irq2), unit);
}
}
@ -242,7 +258,8 @@ promise_intr(int32_t unit)
#endif
static int32_t
ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
pcici_t tag, int32_t *unit)
{
struct ata_softc *scp = atadevices[atanlun];
int32_t mask = 0;
@ -254,7 +271,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
atanlun++;
#endif
if (lun > MAXATA) {
printf("ata: unit of of range(%d)\n", lun);
printf("ata: unit out of range(%d)\n", lun);
return 0;
}
if (scp) {
@ -268,14 +285,15 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
}
bzero(scp, sizeof(struct ata_softc));
scp->unit = lun;
scp->unit = *unit;
scp->lun = lun;
scp->ioaddr = ioaddr;
scp->altioaddr = altioaddr;
scp->active = ATA_IDLE;
#ifdef ATA_DEBUG
printf("ata%d: iobase=0x%04x altiobase=0x%04x\n",
scp->unit, scp->ioaddr, scp->altioaddr);
scp->lun, scp->ioaddr, scp->altioaddr);
#endif
/* do we have any signs of ATA/ATAPI HW being present ? */
@ -291,7 +309,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",
scp->unit, mask, status0, status1);
scp->lun, mask, status0, status1);
#endif
if (!mask) {
free(scp, M_DEVBUF);
@ -305,6 +323,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
outb(scp->altioaddr, ATA_A_IDS);
DELAY(1000);
inb(scp->ioaddr + ATA_ERROR);
DELAY(1);
outb(scp->altioaddr, ATA_A_4BIT);
DELAY(1);
@ -333,7 +352,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",
scp->unit, mask, status0, status1);
scp->lun, mask, status0, status1);
#endif
if (!mask) {
free(scp, M_DEVBUF);
@ -378,18 +397,19 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit)
}
}
#ifdef ATA_DEBUG
printf("ata%d: devices = 0x%x\n", scp->unit, scp->devices);
printf("ata%d: devices = 0x%x\n", scp->lun, scp->devices);
#endif
if (!(scp->devices & (ATA_ATA_MASTER|ATA_ATAPI_MASTER)))
scp->flags |= ATA_F_SLAVE_ONLY;
if (!scp->devices) {
free(scp, M_DEVBUF);
return 0;
}
bufq_init(&scp->ata_queue);
TAILQ_INIT(&scp->atapi_queue);
*unit = scp->unit;
atadevices[scp->unit] = scp;
*unit = scp->lun;
scp->tag = tag;
if (bmaddr)
scp->bmaddr = bmaddr;
atadevices[scp->lun] = scp;
#ifndef ATA_STATIC_ID
atanlun++;
#endif
@ -402,12 +422,8 @@ ataintr(int32_t unit)
struct ata_softc *scp;
struct atapi_request *atapi_request;
struct buf *ata_request;
static int32_t intcount = 0;
#ifdef ATA_DEBUG
printf("ataintr: entered unit=%d\n", unit);
#endif
if (unit < 0 || unit > atanlun) {
printf("ataintr: unit %d unusable\n", unit);
return;
@ -439,8 +455,9 @@ ataintr(int32_t unit)
default:
case ATA_IDLE:
if (intcount++ < 5)
printf("ata%d: unwanted interrupt\n", unit);
if (intcount++ < 10)
printf("ata%d: unwanted interrupt %d\n", unit, intcount);
inb(scp->ioaddr + ATA_STATUS);
return;
}
scp->active = ATA_IDLE;
@ -456,34 +473,48 @@ ata_start(struct ata_softc *scp)
#ifdef ATA_DEBUG
printf("ata_start: entered\n");
#endif
if (scp->active) {
if (scp->active != ATA_IDLE) {
printf("ata: unwanted ata_start\n");
return;
}
#if NATADISK > 0
/* find & call the responsible driver if anything on ATA queue */
if ((ata_request = bufq_first(&scp->ata_queue))) {
scp->active = ATA_ACTIVE_ATA;
ad_transfer(ata_request);
#ifdef ATA_DEBUG
printf("ata_start: started ata, leaving\n");
#endif
return;
}
#endif
/* find & call the responsible driver if anything on ATAPI queue */
if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) {
scp->active = ATA_ACTIVE_ATAPI;
atapi_transfer(atapi_request);
#ifdef ATA_DEBUG
printf("ata_start: started atapi, leaving\n");
#endif
return;
}
}
int32_t
ata_wait(struct ata_softc *scp, u_int8_t mask)
ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
{
u_int8_t status;
u_int32_t timeout = 0;
while (timeout++ <= 50000) { /* timeout 5 secs */
while (timeout++ <= 500000) { /* timeout 5 secs */
status = inb(scp->ioaddr + ATA_STATUS);
if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
/* if drive fails status, reselect the drive just to be sure */
if (status == 0xff) {
printf("ata%d: %s: no status, reselecting device\n",
scp->lun, device?"slave":"master");
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device);
DELAY(1);
status = inb(scp->ioaddr + ATA_STATUS);
}
@ -507,21 +538,25 @@ ata_wait(struct ata_softc *scp, u_int8_t mask)
int32_t
ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
u_int32_t cylinder, u_int32_t head, u_int32_t sector,
u_int32_t count, int32_t flags)
u_int32_t count, u_int32_t feature, int32_t flags)
{
#ifdef ATA_DEBUG
printf("ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=%d, flags=%02x\n", scp->ioaddr, device, command, cylinder, head, sector, count, flags);
#endif
/* ready to issue command ? */
if (ata_wait(scp, 0) < 0) {
printf("ata_command: timeout waiting to give command");
return -1;
if (ata_wait(scp, device, 0) < 0) {
printf("ata%d: %s: timeout waiting to give command s=%02x e=%02x\n",
scp->lun, device?"slave":"master", scp->status, scp->error);
}
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head);
outb(scp->ioaddr + ATA_PRECOMP, 0); /* no precompensation */
outb(scp->ioaddr + ATA_FEATURE, feature);
outb(scp->ioaddr + ATA_CYL_LSB, cylinder);
outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8);
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head);
outb(scp->ioaddr + ATA_SECTOR, sector);
outb(scp->ioaddr + ATA_COUNT, count);
if (scp->active && flags != ATA_IMMEDIATE)
if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE)
printf("DANGER active=%d\n", scp->active);
switch (flags) {
@ -545,6 +580,9 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
outb(scp->ioaddr + ATA_CMD, command);
break;
}
#ifdef ATA_DEBUG
printf("ata_command: leaving\n");
#endif
return 0;
}
@ -587,4 +625,4 @@ bpack(int8_t *src, int8_t *dst, int32_t len)
}
dst[j] = 0x00;
}
#endif
#endif /* NATA > 0 */

View File

@ -25,22 +25,28 @@
* (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/05 09:43:30 sos Exp $
* $Id: ata-all.h,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
/* ATA register defines */
#define ATA_DATA 0x00 /* data register */
#define ATA_ERROR 0x01 /* (R) error register */
#define ATA_PRECOMP 0x01 /* (W) precompensation */
#define ATA_COUNT 0x02 /* sector count */
#define ATA_FEATURE 0x01 /* (W) feature register */
#define ATA_F_DMA 0x01 /* enable DMA */
#define ATA_F_OVL 0x02 /* enable overlap */
#define ATA_COUNT 0x02 /* (W) sector count */
#define ATA_IREASON 0x02 /* (R) interrupt reason */
#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */
#define ATA_I_IN 0x02 /* read (1) | write (0) */
#define ATA_I_RELEASE 0x04 /* released bus (1) */
#define ATA_I_TAGMASK 0xf8 /* tag mask */
#define ATA_SECTOR 0x03 /* sector # */
#define ATA_CYL_LSB 0x04 /* cylinder# LSB */
#define ATA_CYL_MSB 0x05 /* cylinder# MSB */
#define ATA_DRIVE 0x06 /* Sector/Drive/Head register */
#define ATA_D_LBA 0x40 /* use LBA adressing */
#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */
#define ATA_CMD 0x07 /* command register */
@ -51,15 +57,21 @@
#define ATA_C_READ_MULTI 0xc4 /* read multi command */
#define ATA_C_WRITE_MULTI 0xc5 /* write multi command */
#define ATA_C_SET_MULTI 0xc6 /* set multi size command */
#define ATA_C_PACKET_CMD 0xa0 /* set multi size command */
#define ATA_C_READ_DMA 0xc8 /* read w/DMA command */
#define ATA_C_WRITE_DMA 0xca /* write w/DMA command */
#define ATA_C_PACKET_CMD 0xa0 /* packet command */
#define ATA_C_SETFEATURES 0xef /* features command */
#define ATA_C_FEA_SETXFER 0x03 /* set transfer mode */
#define ATA_STATUS 0x07 /* status register */
#define ATA_S_ERROR 0x01 /* error */
#define ATA_S_INDEX 0x02 /* index */
#define ATA_S_CORR 0x04 /* data corrected */
#define ATA_S_DRQ 0x08 /* data request */
#define ATA_S_DSC 0x10 /* drive Seek Completed */
#define ATA_S_DSC 0x10 /* drive seek completed */
#define ATA_S_SERV 0x10 /* drive needs service */
#define ATA_S_DWF 0x20 /* drive write fault */
#define ATA_S_DMRD 0x20 /* DMA ready */
#define ATA_S_DRDY 0x40 /* drive ready */
#define ATA_S_BSY 0x80 /* busy */
@ -68,28 +80,57 @@
#define ATA_A_RESET 0x04 /* RESET controller */
#define ATA_A_4BIT 0x08 /* 4 head bits */
/* Misc defines */
/* misc defines */
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10
#define ATA_IOSIZE 0x08
#define ATA_OP_FINISHED 0x00
#define ATA_OP_CONTINUES 0x01
/* Devices types */
/* devices types */
#define ATA_ATA_MASTER 0x01
#define ATA_ATA_SLAVE 0x02
#define ATA_ATAPI_MASTER 0x04
#define ATA_ATAPI_SLAVE 0x08
/* Structure describing an ATA device */
struct ata_softc {
u_int32_t unit; /* this instance's number */
u_int32_t ioaddr; /* port addr */
u_int32_t altioaddr; /* alternate port addr */
void *dmacookie; /* handle for DMA services */
int32_t flags; /* controller flags */
#define ATA_F_SLAVE_ONLY 0x0001
/* busmaster DMA related defines */
#define ATA_BM_OFFSET1 0x08
#define ATA_DMA_ENTRIES 256
#define ATA_DMA_EOT 0x80000000
#define ATA_BMCMD_PORT 0x00
#define ATA_BMCMD_START_STOP 0x01
#define ATA_BMCMD_WRITE_READ 0x08
#define ATA_BMSTAT_PORT 0x02
#define ATA_BMSTAT_MASK 0x07
#define ATA_BMSTAT_ACTIVE 0x01
#define ATA_BMSTAT_ERROR 0x02
#define ATA_BMSTAT_INTERRUPT 0x04
#define ATA_BMSTAT_DMA_MASTER 0x20
#define ATA_BMSTAT_DMA_SLAVE 0x40
#define ATA_BMDTP_PORT 0x04
#define ATA_WDMA2 0x22
#define ATA_UDMA2 0x42
/* structure for holding DMA address data */
struct ata_dmaentry {
u_int32_t base;
u_int32_t count;
};
/* structure describing an ATA device */
struct ata_softc {
int32_t unit; /* unit on this controller */
int32_t lun; /* logical unit # */
pcici_t tag; /* PCI tag for this device */
int32_t ioaddr; /* port addr */
int32_t altioaddr; /* alternate port addr */
int32_t bmaddr; /* bus master DMA port */
struct ata_dmaentry *dmatab[2]; /* DMA transfer tables */
int32_t flags; /* controller flags */
int32_t devices; /* what is present */
u_int8_t status; /* last controller status */
u_int8_t error; /* last controller error */
@ -111,8 +152,13 @@ extern struct ata_softc *atadevices[];
/* public prototypes */
void ata_start(struct ata_softc *);
int32_t ata_wait(struct ata_softc *, u_int8_t);
int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t);
int32_t ata_wait(struct ata_softc *, int32_t, u_int8_t);
int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t);
int32_t ata_dmainit(struct ata_softc *, int32_t, int32_t, int32_t, int32_t);
int32_t ata_dmasetup(struct ata_softc *, int32_t, int8_t *, int32_t, int32_t);
void ata_dmastart(struct ata_softc *, int32_t);
int32_t ata_dmastatus(struct ata_softc *, int32_t);
int32_t ata_dmadone(struct ata_softc *, int32_t);
void bswap(int8_t *, int32_t);
void btrim(int8_t *, int32_t);
void bpack(int8_t *, int8_t *, int32_t);

View File

@ -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.3 1999/03/05 09:43:30 sos Exp $
* $Id: ata-disk.c,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
#include "ata.h"
@ -51,6 +51,7 @@
#include <sys/devfsext.h>
#endif
#include <machine/clock.h>
#include <pci/pcivar.h>
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <dev/ata/ata-all.h>
@ -64,12 +65,16 @@ static d_ioctl_t adioctl;
static d_strategy_t adstrategy;
static d_psize_t adpsize;
#define BDEV_MAJOR 0
#define CDEV_MAJOR 3
#define BDEV_MAJOR 30
#define CDEV_MAJOR 116
static struct cdevsw ad_cdevsw = {
adopen, adclose, adread, adwrite,
adioctl, nostop, nullreset, nodevtotty,
#ifdef NOTYET /* the boot code needs to be fixed to boot arbitrary devices */
seltrue, nommap, adstrategy, "ad",
#else
seltrue, nommap, adstrategy, "wd",
#endif
NULL, -1, nodump, adpsize,
D_DISK, 0, -1
};
@ -85,12 +90,45 @@ static void ad_strategy(struct buf *);
static void ad_start(struct ad_softc *);
static void ad_sleep(struct ad_softc *, int8_t *);
static int8_t ad_version(u_int16_t);
int32_t ad_timeout(char *data);
static void ad_drvinit(void);
static struct ad_softc *adtab[NUNIT];
static int32_t adnlun = 0; /* number of config'd drives */
static struct intr_config_hook *ad_attach_hook;
static __inline int
apiomode(struct ata_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 ata_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 ata_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
ad_attach(void *notused)
{
@ -100,7 +138,8 @@ ad_attach(void *notused)
int8_t revision_buf[8+1];
/* now, run through atadevices and look for ATA disks */
for (ctlr=0; ctlr<MAXATA && atadevices[ctlr]; ctlr++) {
for (ctlr=0; ctlr<MAXATA; ctlr++) {
if (!atadevices[ctlr]) continue;
for (dev=0; dev<2; dev++) {
if (atadevices[ctlr]->devices &
(dev ? ATA_ATA_SLAVE : ATA_ATA_MASTER)) {
@ -132,16 +171,26 @@ ad_attach(void *notused)
adp->total_secs = adp->ata_parm->lbasize;
adp->cylinders = adp->total_secs/(adp->heads*adp->sectors);
}
if (adp->ata_parm->atavalid & ATA_FLAG_54_58 &&
adp->ata_parm->lbasize)
adp->flags |= AD_F_USE_LBA;
/* support multiple sectors / interrupt ? */
/* use multiple sectors/interrupt if device supports it */
adp->transfersize = DEV_BSIZE;
secsperint = min(adp->ata_parm->nsecperint, 16);
if (!ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI,
0, 0, 0, secsperint, ATA_WAIT_INTR) &&
ata_wait(adp->controller, ATA_S_DRDY) >= 0)
0, 0, 0, secsperint, 0, ATA_WAIT_INTR) &&
ata_wait(adp->controller, adp->unit, ATA_S_DRDY) >= 0)
adp->transfersize *= secsperint;
/* use DMA if drive & controller supports it */
if (!ata_dmainit(adp->controller, adp->unit,
apiomode(adp->ata_parm),
wdmamode(adp->ata_parm),
udmamode(adp->ata_parm)))
adp->flags |= AD_F_DMA_ENABLED;
bpack(adp->ata_parm->model, model_buf, sizeof(model_buf));
bpack(adp->ata_parm->revision, revision_buf,
sizeof(revision_buf));
@ -160,9 +209,15 @@ ad_attach(void *notused)
adp->heads,
adp->sectors,
DEV_BSIZE);
printf("ad%d: %d secs/int, %d depth queue \n",
printf("ad%d: piomode=%d, dmamode=%d, udmamode=%d\n",
adnlun,
apiomode(adp->ata_parm),
wdmamode(adp->ata_parm),
udmamode(adp->ata_parm));
printf("ad%d: %d secs/int, %d depth queue, %s mode\n",
adnlun, adp->transfersize / DEV_BSIZE,
adp->ata_parm->queuelen & 0x1f);
adp->ata_parm->queuelen & 0x1f,
(adp->flags & AD_F_DMA_ENABLED) ? "DMA" :"PIO");
devstat_add_entry(&adp->stats, "ad", adnlun, DEV_BSIZE,
DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE,
@ -193,9 +248,13 @@ ad_getparam(struct ad_softc *adp)
struct ata_params *ata_parm;
int8_t buffer[DEV_BSIZE];
/* select drive */
outb(adp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | adp->unit);
DELAY(1);
ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY,
0, 0, 0, 0, ATA_WAIT_INTR);
if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
0, 0, 0, 0, 0, ATA_WAIT_INTR);
if (ata_wait(adp->controller, adp->unit,
ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
return -1;
insw(adp->controller->ioaddr + ATA_DATA, buffer,
sizeof(buffer)/sizeof(int16_t));
@ -226,6 +285,7 @@ printf("adopen: lun=%d adnlun=%d\n", lun, adnlun);
return ENXIO;
/* spinwait if anybody else is reading the disk label */
/* is this needed anymore ?? SOS XXX */
while (adp->flags & AD_F_LABELLING)
tsleep((caddr_t)&adp->flags, PZERO - 1, "adop1", 1);
@ -316,22 +376,20 @@ printf("adstrategy: entered\n");
if (dscheck(bp, adp->slices) <= 0)
goto done;
s = splbio();
/* hang around if somebody else is labelling */
if (adp->flags & AD_F_LABELLING)
ad_sleep(adp, "adlab");
s = splbio();
bufqdisksort(&adp->queue, bp);
if (!adp->active)
ad_start(adp);
if (!adp->controller->active)
if (adp->controller->active == ATA_IDLE)
ata_start(adp->controller);
devstat_start_transaction(&adp->stats);
splx(s);
return;
@ -373,8 +431,9 @@ printf("ad_start:\n");
if (!(bp = bufq_first(&adp->queue)))
return;
bp->b_driver1 = adp;
/* remove from drive queue */
bufq_remove(&adp->queue, bp);
bp->b_driver1 = adp;
/* link onto controller queue */
bufq_insert_tail(&adp->controller->ata_queue, bp);
@ -403,41 +462,70 @@ ad_transfer(struct buf *bp)
/* setup transfer parameters */
adp->bytecount = bp->b_bcount;
secsprcyl = adp->sectors * adp->heads;
cylinder = blknum / secsprcyl;
head = (blknum % secsprcyl) / adp->sectors;
sector = blknum % adp->sectors;
count = howmany(adp->bytecount, DEV_BSIZE);
if (count > 255) /* SOS */
printf("ad_transfer: count=%d\n", count);
if (adp->flags & AD_F_USE_LBA) {
sector = (blknum >> 0) & 0xff;
cylinder = (blknum >> 8) & 0xffff;
head = ((blknum >> 24) & 0xf) | ATA_D_LBA;
}
else {
secsprcyl = adp->sectors * adp->heads;
cylinder = blknum / secsprcyl;
head = (blknum % secsprcyl) / adp->sectors;
sector = (blknum % adp->sectors) + 1;
}
/* setup transfer length if multible sector access present */
/* setup first transfer length */
adp->currentsize = min(adp->bytecount, adp->transfersize);
if (adp->currentsize > DEV_BSIZE)
devstat_start_transaction(&adp->stats);
/* does this drive & transfer work with DMA ? */
adp->flags &= ~AD_F_DMA_USED;
if ((adp->flags & AD_F_DMA_ENABLED) &&
!ata_dmasetup(adp->controller, adp->unit,
(void *)bp->b_data, adp->bytecount,
(bp->b_flags & B_READ))) {
adp->flags |= AD_F_DMA_USED;
command = (bp->b_flags&B_READ) ? ATA_C_READ_DMA : ATA_C_WRITE_DMA;
adp->currentsize = adp->bytecount;
}
/* does this drive support multi sector transfers ? */
else if (adp->currentsize > DEV_BSIZE)
command = (bp->b_flags&B_READ) ? ATA_C_READ_MULTI:ATA_C_WRITE_MULTI;
else
command = (bp->b_flags&B_READ) ? ATA_C_READ : ATA_C_WRITE;
ata_command(adp->controller, adp->unit, command, cylinder, head,
sector + 1, count, ATA_IMMEDIATE);
sector, count, 0, ATA_IMMEDIATE);
}
/* if this is a read operation, return and wait for interrupt */
/* if this is a DMA transaction start it, return and wait for interrupt */
if (adp->flags & AD_F_DMA_USED) {
ata_dmastart(adp->controller, adp->unit);
#ifdef AD_DEBUG
printf("ad_transfer: return waiting for DMA interrupt\n");
#endif
return;
}
/* calculate this transfer length */
adp->currentsize = min(adp->bytecount, adp->transfersize);
/* if this is a PIO read operation, return and wait for interrupt */
if (bp->b_flags & B_READ) {
#ifdef AD_DEBUG
printf("ad_transfer: return waiting to read data\n");
printf("ad_transfer: return waiting for PIO read interrupt\n");
#endif
return;
}
/* ready to write data ? */
if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) < 0) {
/* ready to write PIO data ? */
if (ata_wait(adp->controller, adp->unit,
ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) < 0) {
printf("ad_transfer: timeout waiting for DRQ");
}
/* calculate transfer length */
adp->currentsize = min(adp->bytecount, adp->transfersize);
/* output the data */
#if 0
@ -459,14 +547,22 @@ int32_t
ad_interrupt(struct buf *bp)
{
struct ad_softc *adp = bp->b_driver1;
int32_t dma_stat = 0;
/* finish DMA stuff */
/* finish DMA transfer */
if (adp->flags & AD_F_DMA_USED) {
if (!(ata_dmastatus(adp->controller, adp->unit) & ATA_BMSTAT_INTERRUPT)){
printf("extra SMP interrupt\n");
return ATA_OP_CONTINUES;
}
dma_stat = ata_dmadone(adp->controller, adp->unit);
}
/* get drive status */
if (ata_wait(adp->controller, 0) < 0)
printf("ad_interrupt: timeout waiting for status");
if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR)) {
if (ata_wait(adp->controller, adp->unit, 0) < 0)
printf("ad_interrupt: timeout waiting for status");
if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR) ||
(adp->flags & AD_F_DMA_USED && dma_stat != ATA_BMSTAT_INTERRUPT)) {
oops:
printf("ad%d: status=%02x error=%02x\n",
adp->lun, adp->controller->status, adp->controller->error);
@ -478,23 +574,23 @@ ad_interrupt(struct buf *bp)
if (adp->controller->status & ATA_S_CORR)
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) {
/* if this was a PIO read operation, get the data */
if (adp->active && !(adp->flags & AD_F_DMA_USED) &&
((bp->b_flags & (B_READ | B_ERROR)) == B_READ)) {
/* ready to receive data? */
if ((adp->controller->status & (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
!= (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
printf("ad_interrupt: read interrupt arrived early");
if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) != 0){
if (ata_wait(adp->controller, adp->unit,
ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) != 0){
printf("ad_interrupt: read error detected late");
goto oops;
}
/* calculate transfer length */
adp->currentsize = min(adp->bytecount, adp->currentsize);
/* data are ready, get them */
/* data ready, read in */
#if 0
insw(adp->controller->ioaddr + ATA_DATA,
(void *)((int32_t)bp->b_data + adp->donecount),
@ -510,26 +606,30 @@ ad_interrupt(struct buf *bp)
#endif
}
/* if this was a DMA operation finish up */
if (adp->active && (adp->flags & AD_F_DMA_USED) && !(bp->b_flags & B_ERROR))
adp->bytecount -= adp->currentsize;
/* finish up this tranfer, check for more work on this buffer */
if (adp->controller->active) {
if (adp->controller->active == ATA_ACTIVE_ATA) {
if ((bp->b_flags & B_ERROR) == 0) {
adp->donecount += adp->currentsize;
#ifdef AD_DEBUG
printf("ad_interrupt: %s operation OK\n", (bp->b_flags & B_READ)?"R":"W");
printf("ad_interrupt: %s op OK\n", (bp->b_flags & B_READ)?"R":"W");
#endif
if (adp->bytecount > 0) {
ad_transfer(bp); /* MESSY!! only needed for W */
ad_transfer(bp);
return ATA_OP_CONTINUES;
}
}
bufq_remove(&adp->controller->ata_queue, bp);
bp->b_resid = bp->b_bcount - adp->donecount;
adp->donecount = 0;
biodone(bp);
devstat_end_transaction(&adp->stats, bp->b_bcount - bp->b_resid,
DEVSTAT_TAG_NONE,
(bp->b_flags & B_READ) ?
DEVSTAT_READ : DEVSTAT_WRITE);
biodone(bp);
adp->donecount = 0;
adp->active = 0;
}
ad_start(adp);
@ -544,7 +644,7 @@ ad_sleep(struct ad_softc *adp, int8_t *mesg)
{
int32_t s = splbio();
while (adp->controller->active)
while (adp->controller->active != ATA_IDLE)
tsleep((caddr_t)&adp->controller->active, PZERO - 1, mesg, 1);
splx(s);
}
@ -569,6 +669,7 @@ ad_drvinit(void)
if (!ad_devsw_installed) {
cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &ad_cdevsw);
cdevsw_add_generic(0, 3, &ad_cdevsw); /* grap wd entries too */
ad_devsw_installed = 1;
}
/* register callback for when interrupts are enabled */

View File

@ -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.h,v 1.3 1999/03/05 09:43:30 sos Exp $
* $Id: ata-disk.h,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
/* ATA device parameter information */
@ -37,7 +37,7 @@ struct ata_params {
int16_t unfbytespertrk; /* # unformatted bytes/track */
int16_t unfbytes; /* # unformatted bytes/sector */
u_int16_t sectors; /* # sectors/track */
int16_t vendorunique[3];
int16_t vendorunique0[3];
int8_t serial[20]; /* serial number */
int16_t buffertype; /* buffer type */
#define ATA_BT_SINGLEPORTSECTOR 1 /* 1 port, 1 sector buffer */
@ -51,14 +51,27 @@ struct ata_params {
int8_t nsecperint; /* sectors per interrupt */
int8_t vendorunique1;
int16_t usedmovsd; /* double word read/write? */
int8_t vendorunique2;
int8_t capability; /* various capability bits */
int16_t cap_validate; /* validation for above */
u_int8_t vendorcap; /* vendor capabilities */
u_int8_t dmaflag :1; /* DMA supported - always 1 */
u_int8_t lbaflag :1; /* LBA supported - always 1 */
u_int8_t iordydis :1; /* IORDY may be disabled */
u_int8_t iordyflag :1; /* IORDY supported */
u_int8_t :1;
u_int8_t standby :1; /* standby timer supported */
u_int8_t :1;
u_int8_t :1;
int16_t capvalidate; /* validation for above */
int8_t vendorunique3;
int8_t opiomode; /* PIO modes 0-2 */
int8_t vendorunique4;
int8_t odmamode; /* old DMA modes, not ATA-3 */
int16_t atavalid; /* fields valid */
#define ATA_FLAG_54_58 1 /* words 54-58 valid */
#define ATA_FLAG_64_70 2 /* words 64-70 valid */
int16_t currcyls;
int16_t currheads;
int16_t currsectors;
@ -67,17 +80,20 @@ struct ata_params {
int8_t currmultsect;
int8_t multsectvalid;
int32_t lbasize;
int16_t dmasword; /* obsolete in ATA-3 */
int16_t dmamword; /* multiword DMA modes */
int16_t eidepiomodes; /* advanced PIO modes */
int16_t eidedmamin; /* fastest DMA timing */
int16_t eidedmanorm; /* recommended DMA timing */
int16_t eidepioblind; /* fastest possible blind PIO */
int16_t eidepioacked; /* fastest possible IORDY PIO */
int16_t sdmamodes; /* singleword DMA modes */
int16_t wdmamodes; /* multiword DMA modes */
int16_t apiomodes; /* advanced PIO modes */
u_int16_t mwdmamin; /* min. M/W DMA time/word ns */
u_int16_t mwdmarec; /* rec. M/W DMA time ns */
u_int16_t pioblind; /* min. PIO cycle w/o flow */
u_int16_t pioiordy; /* min. PIO cycle IORDY flow */
int16_t reserved69;
int16_t reserved70;
int16_t reserved71;
int16_t reserved72;
u_int16_t rlsovlap; /* rel time (us) for overlap */
u_int16_t rlsservice; /* rel time (us) for service */
int16_t reserved73;
int16_t reserved74;
int16_t queuelen;
@ -93,7 +109,7 @@ struct ata_params {
int16_t featenab1;
int16_t featenab2;
int16_t featenab3;
int16_t udmamode; /* UltraDMA modes */
int16_t udmamodes; /* UltraDMA modes */
int16_t erasetime;
int16_t enherasetime;
int16_t apmlevel;
@ -120,8 +136,13 @@ struct ad_softc {
u_int32_t donecount; /* bytes transferred */
u_int32_t active; /* active processing request */
u_int32_t flags; /* drive flags */
struct devstat stats; /* devstat entry */
#define AD_F_LABELLING 0x0001
#define AD_F_USE_LBA 0x0002
#define AD_F_USE_32BIT 0x0004
#define AD_F_DMA_ENABLED 0x0008
#define AD_F_DMA_USED 0x0010
struct devstat stats; /* devstat entry */
#ifdef DEVFS
void *cdevs_token;
void *bdevs_token;

366
sys/dev/ata/ata-dma.c Normal file
View File

@ -0,0 +1,366 @@
/*-
* 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"
#if NATA > 0
#include "pci.h"
#if NPCI > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/buf.h>
#include <sys/malloc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <dev/ata/ata-all.h>
/* misc defines */
#define MIN(a,b) ((a)>(b)?(b):(a))
int32_t
ata_dmainit(struct ata_softc *scp, int32_t device,
int32_t apiomode, int32_t wdmamode, int32_t udmamode)
{
int32_t type, devno, error;
void *dmatab;
if (!scp->bmaddr)
return -1;
#ifdef ATA_DEBUGDMA
printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n",
scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr);
#endif
if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT)))
return -1;
if (((int)dmatab>>PAGE_SHIFT)^(((int)dmatab+PAGE_SIZE-1)>>PAGE_SHIFT)) {
printf("ata_dmainit: dmatab crosses page boundary, no DMA\n");
free(dmatab, M_DEVBUF);
return -1;
}
scp->dmatab[device ? 1 : 0] = dmatab;
type = pci_conf_read(scp->tag, PCI_ID_REG);
switch(type) {
case 0x71118086: /* Intel PIIX4 */
if (udmamode >= 2) {
int32_t mask48, new48;
printf("ata%d: %s: settting up UDMA2 mode on PIIX4 chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
devno = (scp->unit << 1) + (device) ? 1 : 0;
mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
new48 = (1 << devno) + (2 << (16 + (devno << 2)));
pci_conf_write(scp->tag, 0x48,
(pci_conf_read(scp->tag, 0x48) & ~mask48) | new48);
return 0;
}
/* FALLTHROUGH */
case 0x70108086: /* Intel PIIX3 */
if (wdmamode >= 2 && apiomode >= 4) {
int32_t mask40, new40, mask44, new44;
/* if SITRE not set doit for both channels */
if (!((pci_conf_read(scp->tag, 0x40) >> (scp->unit<<8)) & 0x4000)) {
new40 = pci_conf_read(scp->tag, 0x40);
new44 = pci_conf_read(scp->tag, 0x44);
if (!(new40 & 0x00004000)) {
new44 &= ~0x0000000f;
new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8);
}
if (!(new40 & 0x40000000)) {
new44 &= ~0x000000f0;
new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20);
}
new40 |= 0x40004000;
pci_conf_write(scp->tag, 0x40, new40);
pci_conf_write(scp->tag, 0x44, new44);
}
printf("ata%d: %s: settting up WDMA2 mode on PIIX3/4 chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
if (device == ATA_MASTER) {
mask40 = 0x0000330f;
new40 = 0x00002307;
mask44 = 0;
new44 = 0;
} else {
mask40 = 0x000000f0;
new40 = 0x00000070;
mask44 = 0x0000000f;
new44 = 0x0000000b;
}
if (scp->unit) {
mask40 <<= 16;
new40 <<= 16;
mask44 <<= 4;
new44 <<= 4;
}
pci_conf_write(scp->tag, 0x40,
(pci_conf_read(scp->tag, 0x40) & ~mask40) | new40);
pci_conf_write(scp->tag, 0x44,
(pci_conf_read(scp->tag, 0x44) & ~mask44) | new44);
return 0;
}
break;
case 0x12308086: /* Intel PIIX */
/* probably not worth the trouble */
break;
case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */
devno = (scp->unit << 1) + (device) ? 1 : 0;
if (udmamode >=2) {
outb(scp->bmaddr + 0x1f, inb(scp->bmaddr + 0x1f) | 0x01);
pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004127f3);
printf("ata%d: %s: settting up UDMA2 mode on Promise chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
}
else if (wdmamode >= 2 && apiomode >= 4) {
outb(scp->bmaddr + 0x1f, inb(scp->bmaddr + 0x1f) | 0x01);
pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004367f3);
printf("ata%d: %s: settting up WDMA2 mode on Promise chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
}
else {
pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004fe924);
printf("ata%d: %s: settting up PIO mode on Promise chip OK\n",
scp->lun, (device) ? "slave" : "master");
}
break;
case 0x522910b9: /* AcerLabs Aladdin IV/V */
if (udmamode >=2) {
int32_t word54 = pci_conf_read(scp->tag, 0x54);
printf("ata%d: %s: settting up UDMA2 mode on Aladdin chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
word54 |= 0x5555;
word54 |= (0x0000000A << (16 + (scp->unit << 3) + (device << 2)));
pci_conf_write(scp->tag, 0x54, word54);
return 0;
}
else if (wdmamode >= 2 && apiomode >= 4) {
printf("ata%d: %s: settting up WDMA2 mode on Aladdin chip ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
return 0;
}
break;
default: /* well, we have no support for this, but try anyways */
if ((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) {
printf("ata%d: %s: settting up generic WDMA2 mode ",
scp->lun, (device) ? "slave" : "master");
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR);
if (error) {
printf("failed\n");
break;
}
printf("OK\n");
return 0;
}
}
free(dmatab, M_DEVBUF);
return -1;
}
int32_t
ata_dmasetup(struct ata_softc *scp, int32_t device,
int8_t *data, int32_t count, int32_t flags)
{
struct ata_dmaentry *dmatab;
u_int32_t dma_count, dma_base;
int32_t i = 0;
#ifdef ATA_DEBUGDMA
printf("ata%d: dmasetup\n", scp->lun);
#endif
if (((u_int32_t)data & 1) || (count & 1))
return -1;
if (!count) {
printf("ata%d: zero length DMA transfer attempt on %s\n",
scp->lun, (device ? "slave" : "master"));
return -1;
}
dmatab = scp->dmatab[device ? 1 : 0];
dma_base = vtophys(data);
dma_count = MIN(count, (PAGE_SIZE - ((u_int32_t)data & PAGE_MASK)));
data += dma_count;
count -= dma_count;
while (count) {
dmatab[i].base = dma_base;
dmatab[i].count = (dma_count & 0xffff);
i++;
if (i >= ATA_DMA_ENTRIES) {
printf("ata%d: too many segments in DMA table for %s\n",
scp->lun, (device ? "slave" : "master"));
return -1;
}
dma_base = vtophys(data);
dma_count = MIN(count, PAGE_SIZE);
data += MIN(count, PAGE_SIZE);
count -= MIN(count, PAGE_SIZE);
}
#ifdef ATA_DEBUGDMA
printf("ata_dmasetup: base=%08x count%08x\n",
dma_base, dma_count);
#endif
dmatab[i].base = dma_base;
dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab));
#ifdef ATA_DEBUGDMA
printf("dmatab=%08x %08x\n", vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT));
#endif
outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0);
outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) |
(ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR)));
return 0;
}
void
ata_dmastart(struct ata_softc *scp, int32_t device)
{
#ifdef ATA_DEBUGDMA
printf("ata%d: dmastart\n", scp->lun);
#endif
outb(scp->bmaddr + ATA_BMCMD_PORT,
inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP);
}
int32_t
ata_dmadone(struct ata_softc *scp, int32_t device)
{
#ifdef ATA_DEBUGDMA
printf("ata%d: dmadone\n", scp->lun);
#endif
outb(scp->bmaddr + ATA_BMCMD_PORT,
inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
}
int32_t
ata_dmastatus(struct ata_softc *scp, int32_t device)
{
#ifdef ATA_DEBUGDMA
printf("ata%d: dmastatus\n", scp->lun);
#endif
return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
}
#else /* NPCI > 0 */
int32_t
ata_dmainit(struct ata_softc *scp, int32_t device,
int32_t piomode, int32_t wdmamode, int32_t udmamode)
{
return -1;
}
int32_t
ata_dmasetup(struct ata_softc *scp, int32_t device,
int8_t *data, int32_t count, int32_t flags)
{
return -1;
}
void
ata_dmastart(struct ata_softc *scp, int32_t device)
{
}
int32_t
ata_dmadone(struct ata_softc *scp, int32_t device)
{
return -1;
}
int32_t
ata_dmastatus(struct ata_softc *scp, int32_t device)
{
return -1;
}
#endif /* NPCI > 0 */
#endif /* NATA > 0 */

View File

@ -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.3 1999/03/05 09:43:30 sos Exp $
* $Id: atapi-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
#include "ata.h"
@ -44,6 +44,7 @@
#include <sys/malloc.h>
#include <sys/devicestat.h>
#include <machine/clock.h>
#include <pci/pcivar.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
@ -54,7 +55,7 @@ static int8_t *atapi_type(int32_t);
#ifdef ATAPI_DEBUG
static int8_t *atapi_cmd2str(u_int8_t);
#endif
int32_t atapi_wait(struct ata_softc *, u_int8_t);
static int32_t atapi_wait(struct atapi_softc *, u_int8_t);
static void atapi_init(void);
/* extern references */
@ -73,7 +74,8 @@ atapi_attach(void *notused)
int8_t revision_buf[8+1];
/* now, run through atadevices and look for ATAPI devices */
for (ctlr=0; ctlr<MAXATA && atadevices[ctlr]; ctlr++) {
for (ctlr=0; ctlr<MAXATA; ctlr++) {
if (!atadevices[ctlr]) continue;
for (dev=0; dev<2; dev++) {
if (atadevices[ctlr]->devices &
(dev ? ATA_ATAPI_SLAVE : ATA_ATAPI_MASTER)) {
@ -84,11 +86,12 @@ atapi_attach(void *notused)
}
bzero(atp, sizeof(struct atapi_softc));
atp->controller = atadevices[ctlr];
atp->unit = (dev) ? ATA_SLAVE : ATA_MASTER;
atp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE;
if (atapi_getparam(atp)) {
free(atp, M_DEVBUF);
continue;
}
switch (atp->atapi_parm->device_type) {
#if NATAPICD > 0
case ATAPI_TYPE_CDROM:
@ -133,9 +136,12 @@ atapi_getparam(struct atapi_softc *atp)
struct atapi_params *atapi_parm;
int8_t buffer[DEV_BSIZE];
/* select drive */
outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
DELAY(1);
ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY,
0, 0, 0, 0, ATA_WAIT_INTR);
if (atapi_wait(atp->controller, ATA_S_DRQ))
0, 0, 0, 0, 0, ATA_WAIT_INTR);
if (atapi_wait(atp, ATA_S_DRQ))
return -1;
insw(atp->controller->ioaddr + ATA_DATA, buffer,
sizeof(buffer)/sizeof(int16_t));
@ -148,8 +154,6 @@ atapi_getparam(struct atapi_softc *atp)
btrim(atapi_parm->model, sizeof(atapi_parm->model));
bswap(atapi_parm->revision, sizeof(atapi_parm->revision));
btrim(atapi_parm->revision, sizeof(atapi_parm->revision));
bswap(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */
btrim(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */
atp->atapi_parm = atapi_parm;
return 0;
}
@ -162,11 +166,10 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
{
struct atapi_request *request;
int32_t error = 0;
int32_t x;
int32_t s;
if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT)))
return -1;
x = splbio();
bzero(request, sizeof(struct atapi_request));
request->device = atp;
request->data = data;
@ -181,13 +184,15 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
bcopy(ccb, request->ccb, request->ccbsize);
/* link onto controller queue */
s = splbio();
TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain);
splx(s);
#ifdef ATAPI_DEBUG
printf("atapi: queued %s cmd\n", atapi_cmd2str(ccb[0]));
#endif
/* try to start controller */
if (!atp->controller->active)
if (atp->controller->active == ATA_IDLE)
ata_start(atp->controller);
if (!callback) {
/* wait for command to complete */
@ -200,7 +205,6 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
#endif
free(request, M_DEVBUF);
}
splx(x);
return error;
}
@ -209,7 +213,7 @@ atapi_transfer(struct atapi_request *request)
{
struct atapi_softc *atp;
int32_t timeout;
int8_t int_reason; /* not needed really */
int8_t reason; /* not needed really */
/* get device params */
atp = request->device;
@ -220,7 +224,7 @@ atapi_transfer(struct atapi_request *request)
/* start ATAPI operation */
ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD,
request->bytecount, 0, 0, 0, ATA_IMMEDIATE);
request->bytecount, 0, 0, 0, 0, ATA_IMMEDIATE);
/* command interrupt device ? just return */
if (atp->atapi_parm->drqtype == ATAPI_DRQT_INTR)
@ -229,9 +233,9 @@ atapi_transfer(struct atapi_request *request)
/* ready to write ATAPI command */
timeout = 5000; /* might be less for fast devices */
while (timeout--) {
int_reason = inb(atp->controller->ioaddr + ATA_COUNT);
reason = inb(atp->controller->ioaddr + ATA_IREASON);
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
if (((int_reason & (ATA_I_CMD | ATA_I_IN)) |
if (((reason & (ATA_I_CMD | ATA_I_IN)) |
(atp->controller->status&(ATA_S_DRQ|ATA_S_BSY))) == ATAPI_P_CMDOUT)
break;
DELAY(20);
@ -263,7 +267,7 @@ printf("atapi_interrupt: enter\n");
atp = request->device;
/* get drive status */
if (atapi_wait(atp->controller, 0) < 0) {
if (atapi_wait(atp, 0) < 0) {
printf("atapi_interrupt: timeout waiting for status");
/* maybe check sense code ?? SOS */
return ATA_OP_FINISHED;
@ -273,7 +277,7 @@ printf("atapi_interrupt: enter\n");
length = inb(atp->controller->ioaddr + ATA_CYL_LSB);
length |= inb(atp->controller->ioaddr + ATA_CYL_MSB) << 8;
reason = (inb(atp->controller->ioaddr + ATA_COUNT)&(ATA_I_CMD|ATA_I_IN)) |
reason = (inb(atp->controller->ioaddr + ATA_IREASON)&(ATA_I_CMD|ATA_I_IN)) |
(atp->controller->status & ATA_S_DRQ);
#ifdef ATAPI_DEBUG
@ -300,15 +304,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason);
printf("atapi_interrupt: write data underrun %d/%d\n",
length, request->bytecount);
outsw(atp->controller->ioaddr + ATA_DATA,
(void *)((int32_t)request->data), /* + donecount ?? */
length / sizeof(int16_t));
(void *)((int32_t)request->data), length / sizeof(int16_t));
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
outw(atp->controller->ioaddr + ATA_DATA, 0);
}
else {
outsw(atp->controller->ioaddr + ATA_DATA,
(void *)((int32_t)request->data), /* + donecount ?? */
length / sizeof(int16_t));
(void *)((int32_t)request->data), length / sizeof(int16_t));
}
request->bytecount -= length;
request->data += length;
@ -323,15 +325,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason);
printf("atapi_interrupt: read data overrun %d/%d\n",
length, request->bytecount);
insw(atp->controller->ioaddr + ATA_DATA,
(void *)((int32_t)request->data), /* + donecount ?? */
length / sizeof(int16_t));
(void *)((int32_t)request->data), length / sizeof(int16_t));
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
inw(atp->controller->ioaddr + ATA_DATA);
}
else {
insw(atp->controller->ioaddr + ATA_DATA,
(void *)((int32_t)request->data), /* + donecount ?? */
length / sizeof(int16_t));
(void *)((int32_t)request->data), length / sizeof(int16_t));
}
request->bytecount -= length;
request->data += length;
@ -378,11 +378,12 @@ atapi_error(struct atapi_softc *atp, int32_t error)
void
atapi_dump(int8_t *label, void *data, int32_t len)
{
u_int8_t *p = data;
u_int8_t *p = data;
printf ("atapi: %s %x", label, *p++);
while (--len > 0) printf ("-%02x", *p++);
printf ("\n");
printf ("atapi: %s %x", label, *p++);
while (--len > 0)
printf ("-%02x", *p++);
printf ("\n");
}
static int8_t *
@ -448,20 +449,21 @@ atapi_cmd2str(u_int8_t cmd)
}
#endif
int32_t
atapi_wait(struct ata_softc *scp, u_int8_t mask)
static int32_t
atapi_wait(struct atapi_softc *atp, u_int8_t mask)
{
u_int8_t status;
u_int32_t timeout = 0;
while (timeout++ <= 500000) { /* timeout 5 secs */
status = inb(scp->ioaddr + ATA_STATUS);
if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(1);
status = inb(scp->ioaddr + ATA_STATUS);
}
status = inb(atp->controller->ioaddr + ATA_STATUS);
/* if drive fails status, reselect the drive just to be sure */
if (status == 0xff) {
outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
DELAY(1);
status = inb(atp->controller->ioaddr + ATA_STATUS);
}
if (!(status & ATA_S_BSY))
break;
DELAY (10);
@ -473,7 +475,7 @@ atapi_wait(struct ata_softc *scp, u_int8_t mask)
/* Wait 50 msec for bits wanted. */
for (timeout=5000; timeout>0; --timeout) {
status = inb(scp->ioaddr + ATA_STATUS);
status = inb(atp->controller->ioaddr + ATA_STATUS);
if ((status & mask) == mask)
return (status & ATA_S_ERROR);
DELAY (10);

View File

@ -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/03 21:10:29 sos Exp $
* $Id: atapi-all.h,v 1.3 1999/03/07 21:49:14 sos Exp $
*/
/* ATAPI misc defines */
@ -50,7 +50,7 @@
#define ATAPI_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */
#define ATAPI_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */
#define ATAPI_SK_UNIT_ATTENTION 0x60 /* media changed */
#define ATAPI_SK_DATA_PROTECT 0x70 /* reading read-protected sec */
#define ATAPI_SK_DATA_PROTECT 0x70 /* write protect */
#define ATAPI_SK_BLANK_CHECK 0x80 /* blank check */
#define ATAPI_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */
#define ATAPI_SK_COPY_ABORTED 0xa0 /* copy aborted */
@ -109,13 +109,25 @@ struct atapi_params {
u_int8_t proto :2; /* command protocol */
#define ATAPI_PROTO_ATAPI 2
int16_t reserved1[9];
int16_t reserved1;
int16_t reserved2;
int16_t reserved3;
int16_t reserved4;
int16_t reserved5;
int16_t reserved6;
int16_t reserved7;
int16_t reserved8;
int16_t reserved9;
int8_t serial[20]; /* serial number */
int16_t reserved2[3];
int16_t reserved20;
int16_t reserved21;
int16_t reserved22;
int8_t revision[8]; /* firmware revision */
int8_t model[40]; /* model name */
int16_t reserved3[2];
u_int8_t vendor_cap; /* vendor capabilities */
int16_t reserved47;
int16_t reserved48;
u_int8_t vendorcap; /* vendor capabilities */
u_int8_t dmaflag :1; /* DMA supported */
u_int8_t lbaflag :1; /* LBA supported - always 1 */
u_int8_t iordydis :1; /* IORDY can be disabled */
@ -124,27 +136,52 @@ struct atapi_params {
u_int8_t ovlapflag :1; /* overlap supported */
u_int8_t :1;
u_int8_t idmaflag :1; /* interleaved DMA supported */
int16_t reserved4;
u_int16_t pio_timing; /* PIO cycle timing */
u_int16_t dma_timing; /* DMA cycle timing */
u_int16_t flags;
int16_t capvalidate; /* validation for above */
u_int16_t piotiming; /* PIO cycle timing */
u_int16_t dmatiming; /* DMA cycle timing */
u_int16_t atavalid; /* fields valid */
#define ATAPI_FLAG_54_58 1 /* words 54-58 valid */
#define ATAPI_FLAG_64_70 2 /* words 64-70 valid */
int16_t reserved5[8];
u_int8_t swdma_flag; /* singleword DMA supported */
u_int8_t swdma_active; /* singleword DMA active */
u_int8_t mwdma_flag; /* multiword DMA supported */
u_int8_t mwdma_active; /* multiword DMA active */
u_int8_t apio_flag; /* advanced PIO supported */
u_int8_t reserved6;
u_int16_t mwdma_min; /* min. M/W DMA time/word ns */
u_int16_t mwdma_dflt; /* rec. M/W DMA time ns */
u_int16_t pio_nfctl_min; /* min. PIO cycle w/o flow */
u_int16_t pio_iordy_min; /* min. PIO cycle IORDY flow */
int16_t reserved7[2];
u_int16_t rls_ovlap; /* rel time (us) for overlap */
u_int16_t rls_service; /* rel time (us) for service */
int16_t reserved54[8];
int16_t sdmamodes; /* singleword DMA modes */
int16_t wdmamodes; /* multiword DMA modes */
int16_t apiomodes; /* advanced PIO modes */
u_int16_t mwdmamin; /* min. M/W DMA time/word ns */
u_int16_t mwdmarec; /* rec. M/W DMA time ns */
u_int16_t pioblind; /* min. PIO cycle w/o flow */
u_int16_t pioiordy; /* min. PIO cycle IORDY flow */
int16_t reserved69;
int16_t reserved70;
u_int16_t rlsovlap; /* rel time (us) for overlap */
u_int16_t rlsservice; /* rel time (us) for service */
int16_t reserved73;
int16_t reserved74;
int16_t queuelen;
int16_t reserved76;
int16_t reserved77;
int16_t reserved78;
int16_t reserved79;
int16_t versmajor;
int16_t versminor;
int16_t featsupp1;
int16_t featsupp2;
int16_t featsupp3;
int16_t featenab1;
int16_t featenab2;
int16_t featenab3;
int16_t udmamodes; /* UltraDMA modes */
int16_t erasetime;
int16_t enherasetime;
int16_t apmlevel;
int16_t reserved92[34];
int16_t rmvcap;
int16_t securelevel;
};
/* ATAPI REQUEST SENSE structure */
@ -186,6 +223,8 @@ struct atapi_request {
int32_t ccbsize; /* size of ccb (12 | 16) */
int32_t flags;
#define A_READ 0x0001
#define ATAPI_F_DMA_ENABLED 0x0002
#define ATAPI_F_DMA_USED 0x0004
u_int32_t bytecount; /* bytes to transfer */
u_int32_t result; /* result code */

View File

@ -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.2 1999/03/03 21:10:29 sos Exp $
* $Id: atapi-cd.c,v 1.3 1999/03/05 09:43:30 sos Exp $
*/
#include "ata.h"
@ -50,6 +50,7 @@
#ifdef DEVFS
#include <sys/devfsext.h>
#endif
#include <pci/pcivar.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-cd.h>
@ -61,8 +62,8 @@ static d_write_t acdwrite;
static d_ioctl_t acdioctl;
static d_strategy_t acdstrategy;
#define CDEV_MAJOR 69
#define BDEV_MAJOR 19
#define BDEV_MAJOR 31
#define CDEV_MAJOR 117
static struct cdevsw acd_cdevsw = {
acdopen, acdclose, acdread, acdwrite,
acdioctl, nostop, nullreset, nodevtotty,
@ -260,7 +261,7 @@ acd_describe(struct acd_softc *cdp)
bpack(cdp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf));
printf("acd%d: <%s/%s> CDROM drive at ata%d as %s\n",
cdp->lun, model_buf, revision_buf,
cdp->atp->controller->unit,
cdp->atp->controller->lun,
(cdp->atp->unit == ATA_MASTER) ? "master" : "slave ");
printf("acd%d: drive speed ", cdp->lun);
@ -268,7 +269,10 @@ acd_describe(struct acd_softc *cdp)
printf("%d - ", cdp->cap.cur_speed * 1000 / 1024);
printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024);
if (cdp->cap.buf_size)
printf(", %dKB cache\n", cdp->cap.buf_size);
printf(", %dKB cache", cdp->cap.buf_size);
if (cdp->atp->flags & ATAPI_F_DMA_ENABLED)
printf(", DMA");
printf("\n");
printf("acd%d: supported read types:", cdp->lun);
comma = 0;
@ -775,7 +779,6 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
frames -= blocks;
lba += blocks;
}
free(buffer, M_TEMP);
if (args->address_format == CD_LBA_FORMAT)
args->address.lba = lba;

View File

@ -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-fd.c,v 1.2 1999/03/05 09:43:30 sos Exp $
* $Id: atapi-fd.c,v 1.3 1999/03/07 21:49:14 sos Exp $
*/
#include "ata.h"
@ -51,6 +51,7 @@
#ifdef DEVFS
#include <sys/devfsext.h>
#endif
#include <pci/pcivar.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-fd.h>
@ -62,8 +63,8 @@ static d_write_t afdwrite;
static d_ioctl_t afdioctl;
static d_strategy_t afdstrategy;
#define CDEV_MAJOR 87
#define BDEV_MAJOR 1
#define BDEV_MAJOR 32
#define CDEV_MAJOR 118
static struct cdevsw afd_cdevsw = {
afdopen, afdclose, afdread, afdwrite,
@ -176,7 +177,7 @@ afd_describe(struct afd_softc *fdp)
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->controller->lun,
(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,
@ -295,9 +296,7 @@ afdstrategy(struct buf *bp)
return;
}
if (dscheck(bp, fdp->slices) <= 0) {
x = splbio();
biodone(bp);
splx(x);
return;
}
x = splbio();

View File

@ -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.3 1999/03/05 09:43:30 sos Exp $
* $Id: atapi-tape.c,v 1.4 1999/03/07 21:49:14 sos Exp $
*/
#include "ata.h"
@ -47,6 +47,7 @@
#include <sys/devfsext.h>
#endif
#include <machine/clock.h>
#include <pci/pcivar.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>
#include <dev/ata/atapi-tape.h>
@ -58,8 +59,8 @@ static d_write_t astwrite;
static d_ioctl_t astioctl;
static d_strategy_t aststrategy;
#define CDEV_MAJOR 90
#define BDEV_MAJOR 24
#define BDEV_MAJOR 33
#define CDEV_MAJOR 119
static struct cdevsw ast_cdevsw = {
astopen, astclose, astread, astwrite,
@ -181,7 +182,7 @@ ast_describe(struct ast_softc *stp)
bpack(stp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf));
printf("ast%d: <%s/%s> tape drive at ata%d as %s\n",
stp->lun, model_buf, revision_buf,
stp->atp->controller->unit,
stp->atp->controller->lun,
(stp->atp->unit == ATA_MASTER) ? "master" : "slave ");
printf("ast%d: ", stp->lun);
switch (stp->header.medium_type) {

View File

@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
# $Id: files.i386,v 1.228 1999/03/10 10:36:29 yokota Exp $
# $Id: files.i386,v 1.229 1999/03/16 13:34:02 sos Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@ -35,6 +35,7 @@ ukbdmap.h optional ukbd_dflt_keymap \
clean "ukbdmap.h"
#
dev/ata/ata-all.c optional ata device-driver
dev/ata/ata-dma.c optional ata device-driver
dev/ata/atapi-all.c optional ata device-driver
dev/ata/ata-disk.c optional atadisk device-driver
dev/ata/atapi-cd.c optional atapicd device-driver