summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2000-01-17 02:04:19 +0000
committersos <sos@FreeBSD.org>2000-01-17 02:04:19 +0000
commit73d5bc432ffa855032af2d3a79d07f7dd49515ac (patch)
tree27aeff474453ba4d32a590e4b72176b77bbfc87a
parent668e3ec014a72ca0849b346ab9f82e12e8c5776d (diff)
downloadFreeBSD-src-73d5bc432ffa855032af2d3a79d07f7dd49515ac.zip
FreeBSD-src-73d5bc432ffa855032af2d3a79d07f7dd49515ac.tar.gz
Add support for the Intel 810 chipset (ICH type of chips)
Prober support for the VIA 82C686, I finally got the right datasheet. Get rid of atapi_wait, merge it into ata_wait. Avoid a couple of races by using asleep instead of tsleep. Always use 16bit transfers on ISA systems. Clear up the atapi_read/write functions.
-rw-r--r--sys/dev/ata/ata-all.c72
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-disk.c36
-rw-r--r--sys/dev/ata/ata-dma.c62
-rw-r--r--sys/dev/ata/atapi-all.c105
-rw-r--r--sys/dev/ata/atapi-cd.c5
6 files changed, 157 insertions, 124 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 253effa..327ee04 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -133,6 +133,7 @@ ata_isaprobe(device_t dev)
if (res) {
isa_set_portsize(dev, res);
*(int *)device_get_softc(dev) = lun;
+ atadevices[lun]->flags |= ATA_USE_16BIT;
return 0;
}
return ENXIO;
@@ -197,6 +198,12 @@ ata_pcimatch(device_t dev)
case 0x71998086:
return "Intel PIIX4 ATA-33 controller";
+ case 0x24118086:
+ return "Intel ICH ATA-66 controller";
+
+ case 0x24218086:
+ return "Intel ICH0 ATA-33 controller";
+
case 0x522910b9:
return "AcerLabs Aladdin ATA-33 controller";
@@ -363,7 +370,18 @@ ata_pciattach(device_t dev)
/* set sector size */
pci_write_config(dev, 0x60, DEV_BSIZE, 2);
pci_write_config(dev, 0x68, DEV_BSIZE, 2);
+
+ /* prepare for ATA-66 on the 82C686 */
+ if (ata_find_dev(dev, 0x06861106))
+ pci_write_config(dev, 0x50,
+ pci_read_config(dev, 0x50, 4) | 0x070f070f, 4);
break;
+
+ case 0x00041103: /* HighPoint HPT366 controller */
+ printf("hpt366: cache_line_size=0x%02x latency_timer=0x%02x min_grant=0x%02x max_latency=0x%02x\n",
+ pci_read_config(dev, 0x0c, 1), pci_read_config(dev, 0x0d, 1),
+ pci_read_config(dev, 0x3e, 1), pci_read_config(dev, 0x3f, 1));
+
}
/* now probe the addresse found for "real" ATA/ATAPI hardware */
@@ -809,30 +827,25 @@ ata_reinit(struct ata_softc *scp)
int32_t
ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
{
- u_int8_t status;
u_int32_t timeout = 0;
-
+
DELAY(1);
- while (timeout <= 5000000) { /* timeout 5 secs */
- status = inb(scp->ioaddr + ATA_STATUS);
+ while (timeout < 5000000) { /* timeout 5 secs */
+ scp->status = inb(scp->ioaddr + ATA_STATUS);
/* if drive fails status, reselect the drive just to be sure */
- if (status == 0xff) {
- printf("ata%d: %s: no status, reselecting device\n",
+ if (scp->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);
- }
- if (status == 0xff)
- return -1;
- scp->status = status;
- if (!(status & ATA_S_BUSY)) {
- if (status & ATA_S_ERROR)
- scp->error = inb(scp->ioaddr + ATA_ERROR);
- if ((status & mask) == mask)
- return (status & ATA_S_ERROR);
+ scp->status = inb(scp->ioaddr + ATA_STATUS);
}
+
+ /* are we done ? */
+ if (!(scp->status & ATA_S_BUSY))
+ break;
+
if (timeout > 1000) {
timeout += 1000;
DELAY(1000);
@@ -841,9 +854,27 @@ ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
timeout += 10;
DELAY(10);
}
- }
- return -1;
-}
+ }
+ if (scp->status & ATA_S_ERROR)
+ scp->error = inb(scp->ioaddr + ATA_ERROR);
+ if (timeout >= 5000000)
+ return -1;
+ if (!mask)
+ return (scp->status & ATA_S_ERROR);
+
+ /* Wait 50 msec for bits wanted. */
+ timeout = 5000;
+ while (timeout--) {
+ scp->status = inb(scp->ioaddr + ATA_STATUS);
+ if ((scp->status & mask) == mask) {
+ if (scp->status & ATA_S_ERROR)
+ scp->error = inb(scp->ioaddr + ATA_ERROR);
+ return (scp->status & ATA_S_ERROR);
+ }
+ DELAY (10);
+ }
+ return -1;
+}
int32_t
ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
@@ -876,8 +907,9 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
if (scp->active != ATA_IDLE)
printf("WARNING: WAIT_INTR active=%s\n", active2str(scp->active));
scp->active = ATA_WAIT_INTR;
+ asleep((caddr_t)scp, PRIBIO, "atacmd", 500);
outb(scp->ioaddr + ATA_CMD, command);
- if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) {
+ if (await(PRIBIO, 500)) {
printf("ata_command: timeout waiting for interrupt\n");
scp->active = ATA_IDLE;
return -1;
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index e6d7c5e..b9f739b 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -148,6 +148,7 @@ struct ata_softc {
int32_t flags; /* controller flags */
#define ATA_DMA_ACTIVE 0x01
#define ATA_ATAPI_DMA_RO 0x02
+#define ATA_USE_16BIT 0x04
int32_t devices; /* what is present */
#define ATA_ATA_MASTER 0x01
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 619f1fe..c288987 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -498,15 +498,15 @@ ad_transfer(struct ad_request *request)
printf("ad_transfer: timeout waiting for DRQ");
/* output the data */
-#ifdef ATA_16BIT_ONLY
- outsw(adp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data + request->donecount),
- request->currentsize / sizeof(int16_t));
-#else
- outsl(adp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data + request->donecount),
- request->currentsize / sizeof(int32_t));
-#endif
+ if (adp->controller->flags & ATA_USE_16BIT)
+ outsw(adp->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)request->data + request->donecount),
+ request->currentsize / sizeof(int16_t));
+ else
+ outsl(adp->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)request->data + request->donecount),
+ request->currentsize / sizeof(int32_t));
+
request->bytecount -= request->currentsize;
}
@@ -589,15 +589,15 @@ oops:
}
/* data ready, read in */
-#ifdef ATA_16BIT_ONLY
- insw(adp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data + request->donecount),
- request->currentsize / sizeof(int16_t));
-#else
- insl(adp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data + request->donecount),
- request->currentsize / sizeof(int32_t));
-#endif
+ if (adp->controller->flags & ATA_USE_16BIT)
+ insw(adp->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)request->data + request->donecount),
+ request->currentsize / sizeof(int16_t));
+ else
+ insl(adp->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)request->data + request->donecount),
+ request->currentsize / sizeof(int32_t));
+
request->bytecount -= request->currentsize;
}
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index d87a81e..fe5288b 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -98,16 +98,20 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
switch (scp->chiptype) {
case 0x71118086: /* Intel PIIX4 */
- case 0x71998086: /* Intel PIIX4 */
+ case 0x71998086: /* Intel PIIX4e */
+ case 0x24118086: /* Intel ICH */
+ case 0x24218086: /* Intel ICH0 */
if (udmamode >= 2) {
int32_t mask48, new48;
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
- printf("ata%d-%s: %s setting up UDMA2 mode on PIIX4 chip\n",
+ printf("ata%d-%s: %s setting up UDMA2 mode on %s chip\n",
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
- (error) ? "failed" : "success");
+ (error) ? "failed" : "success",
+ (scp->chiptype == 0x24118086) ? "ICH" :
+ (scp->chiptype == 0x24218086) ? "ICH0" :"PIIX4");
if (!error) {
mask48 = (1 << devno) + (3 << (16 + (devno << 2)));
new48 = (1 << devno) + (2 << (16 + (devno << 2)));
@@ -143,10 +147,12 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
- printf("ata%d-%s: %s setting up WDMA2 mode on PIIX%s chip\n",
+ printf("ata%d-%s: %s setting up WDMA2 mode on %s chip\n",
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
(error) ? "failed" : "success",
- (scp->chiptype == 0x70108086) ? "3" : "4");
+ (scp->chiptype == 0x70108086) ? "PIIX3" :
+ (scp->chiptype == 0x24118086) ? "ICH" :
+ (scp->chiptype == 0x24218086) ? "ICH0" :"PIIX4");
if (!error) {
if (device == ATA_MASTER) {
mask40 = 0x0000330f;
@@ -251,16 +257,44 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
case 0x05711106: /* VIA 82C571, 82C586, 82C596 & 82C686 */
case 0x74091022: /* AMD 756 */
- /* UDMA4 mode only on 82C686 and AMD 756 */
- if ((udmamode >= 4 && ata_find_dev(scp->dev, 0x06861106)) ||
- (udmamode >= 4 && scp->chiptype == 0x74091022)) {
- error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ /* UDMA modes on 82C686 */
+ if (ata_find_dev(scp->dev, 0x06861106)) {
+ if (udmamode >= 4) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ printf("ata%d-%s: %s setting up UDMA4 mode on VIA chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master":"slave",
+ (error) ? "failed" : "success");
+ if (!error) {
+ pci_write_config(scp->dev, 0x53 - devno, 0xe8, 1);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4;
+ return 0;
+ }
+ }
+ if (udmamode >= 2) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
+ if (bootverbose)
+ printf("ata%d-%s: %s setting up UDMA2 mode on VIA chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master":"slave",
+ (error) ? "failed" : "success");
+ if (!error) {
+ pci_write_config(scp->dev, 0x53 - devno, 0xea, 1);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA2;
+ return 0;
+ }
+ }
+ }
+
+ /* UDMA4 mode on AMD 756 */
+ if (udmamode >= 4 && scp->chiptype == 0x74091022) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
- printf("ata%d-%s: %s setting up UDMA4 mode on %s chip\n",
+ printf("ata%d-%s: %s setting up UDMA4 mode on AMD chip\n",
scp->lun, (device == ATA_MASTER) ? "master":"slave",
- (error) ? "failed" : "success",
- (scp->chiptype == 0x74091022) ? "AMD" : "VIA");
+ (error) ? "failed" : "success");
if (!error) {
pci_write_config(scp->dev, 0x53 - devno, 0xc3, 1);
scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_UDMA4;
@@ -268,11 +302,10 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
}
}
- /* UDMA2 mode only on 82C586 > rev1, 82C596, 82C686, AMD 756 */
+ /* UDMA2 mode only on 82C586 > rev1, 82C596, AMD 756 */
if ((udmamode >= 2 && ata_find_dev(scp->dev, 0x05861106) &&
pci_read_config(scp->dev, 0x08, 1) >= 0x01) ||
(udmamode >= 2 && ata_find_dev(scp->dev, 0x05961106)) ||
- (udmamode >= 2 && ata_find_dev(scp->dev, 0x06861106)) ||
(udmamode >= 2 && scp->chiptype == 0x74091022)) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
@@ -288,7 +321,6 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
}
}
if (wdmamode >= 2 && apiomode >= 4) {
- /* set WDMA2 mode timing */
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY);
if (bootverbose)
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index 7654fb3..07984bca 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -56,7 +56,6 @@ static void atapi_timeout(struct atapi_request *request);
static int8_t *atapi_type(int32_t);
static int8_t *atapi_cmd2str(u_int8_t);
static int8_t *atapi_skey2str(u_int8_t);
-static int32_t atapi_wait(struct atapi_softc *, u_int8_t);
static void atapi_init(void);
/* extern references */
@@ -208,11 +207,11 @@ atapi_getparam(struct atapi_softc *atp)
if (ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY,
0, 0, 0, 0, 0, ATA_WAIT_INTR))
return -1;
- if (atapi_wait(atp, ATA_S_DRQ))
+ if (ata_wait(atp->controller, atp->unit, ATA_S_DRQ))
return -1;
insw(atp->controller->ioaddr + ATA_DATA, buffer,
sizeof(buffer)/sizeof(int16_t));
- if (atapi_wait(atp, 0))
+ if (ata_wait(atp->controller, atp->unit, 0))
return -1;
if (!(atapi_parm = malloc(sizeof(struct atapi_params), M_ATAPI, M_NOWAIT)))
return -1;
@@ -254,6 +253,10 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
/* append onto controller queue and try to start controller */
s = splbio();
+
+ /* if not using callbacks, prepare to sleep for this request */
+ if (!callback)
+ asleep((caddr_t)request, PRIBIO, "atprq", 0);
TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain);
if (atp->controller->active == ATA_IDLE)
ata_start(atp->controller);
@@ -265,7 +268,7 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
}
/* wait for request to complete */
- tsleep((caddr_t)request, PRIBIO, "atprq", 0);
+ await(PRIBIO, 0);
splx(s);
error = request->error;
free(request, M_ATAPI);
@@ -375,13 +378,16 @@ atapi_interrupt(struct atapi_request *request)
if (atp->flags & ATAPI_F_DMA_USED)
dma_stat = ata_dmadone(atp->controller);
- if (atapi_wait(atp, 0) < 0) {
+ /* is this needed anymore ?? SOS XXX */
+#if NOT_ANY_MORE
+ if (ata_wait(atp->controller, atp->unit, 0) < 0) {
printf("%s: timeout waiting for status", atp->devname);
atp->flags &= ~ATAPI_F_DMA_USED;
request->result = inb(atp->controller->ioaddr + ATA_ERROR) |
ATAPI_SK_RESERVED;
goto op_finished;
}
+#endif
if (atp->flags & ATAPI_F_DMA_USED) {
atp->flags &= ~ATAPI_F_DMA_USED;
@@ -552,64 +558,58 @@ static void
atapi_read(struct atapi_request *request, int32_t length)
{
int8_t **buffer = (int8_t **)&request->data;
+ int32_t size = min(request->bytecount, length);
int32_t resid;
if (request->ccb[0] == ATAPI_REQUEST_SENSE)
*buffer = (int8_t *)&request->sense;
+ if (request->device->controller->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)))
+ insw(request->device->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)*buffer), size / sizeof(int16_t));
+ else
+ insl(request->device->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)*buffer), size / sizeof(int32_t));
+
if (request->bytecount < length) {
printf("%s: read data overrun %d/%d\n",
request->device->devname, length, request->bytecount);
-#ifdef ATA_16BIT_ONLY
- insw(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), request->bytecount/sizeof(int16_t));
-#else
- insl(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), request->bytecount/sizeof(int32_t));
-#endif
+
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
inw(request->device->controller->ioaddr + ATA_DATA);
- *buffer += request->bytecount;
- request->bytecount = 0;
- }
- else {
- insw(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
- *buffer += length;
- request->bytecount -= length;
}
+ *buffer += size;
+ request->bytecount -= size;
}
static void
atapi_write(struct atapi_request *request, int32_t length)
{
int8_t **buffer = (int8_t **)&request->data;
+ int32_t size = min(request->bytecount, length);
int32_t resid;
if (request->ccb[0] == ATAPI_REQUEST_SENSE)
*buffer = (int8_t *)&request->sense;
+ if (request->device->controller->flags & ATA_USE_16BIT ||
+ (size % sizeof(int32_t)))
+ outsw(request->device->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)*buffer), size / sizeof(int16_t));
+ else
+ outsl(request->device->controller->ioaddr + ATA_DATA,
+ (void *)((uintptr_t)*buffer), size / sizeof(int32_t));
+
if (request->bytecount < length) {
printf("%s: write data underrun %d/%d\n",
request->device->devname, length, request->bytecount);
-#ifdef ATA_16BIT_ONLY
- outsw(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), request->bytecount/sizeof(int16_t));
-#else
- outsl(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), request->bytecount/sizeof(int32_t));
-#endif
+
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
outw(request->device->controller->ioaddr + ATA_DATA, 0);
- *buffer += request->bytecount;
- request->bytecount = 0;
- }
- else {
- outsw(request->device->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
- *buffer += length;
- request->bytecount -= length;
}
+ *buffer += size;
+ request->bytecount -= size;
}
static void
@@ -731,41 +731,6 @@ atapi_skey2str(u_int8_t skey)
}
}
-static int32_t
-atapi_wait(struct atapi_softc *atp, u_int8_t mask)
-{
- u_int32_t timeout = 0;
-
- DELAY(1);
- while (timeout++ <= 500000) { /* timeout 5 secs */
- atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
-
- /* if drive fails status, reselect the drive just to be sure */
- if (atp->controller->status == 0xff) {
- outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
- DELAY(1);
- atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
- }
- if (!(atp->controller->status & ATA_S_BUSY) &&
- (atp->controller->status & ATA_S_READY))
- break;
- DELAY (10);
- }
- if (timeout <= 0)
- return -1;
- if (!mask)
- return (atp->controller->status & ATA_S_ERROR);
-
- /* Wait 50 msec for bits wanted. */
- for (timeout=5000; timeout>0; --timeout) {
- atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
- if ((atp->controller->status & mask) == mask)
- return (atp->controller->status & ATA_S_ERROR);
- DELAY (10);
- }
- return -1;
-}
-
static void
atapi_init(void)
{
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 50632f7..458f5a9 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -966,10 +966,13 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
break;
case CDRIOCCLOSEDISK:
- if (!(cdp->flags & F_WRITTEN) || !(cdp->flags & F_DISK_OPEN)) {
+ if (!(cdp->flags & F_DISK_OPEN)) {
error = EINVAL;
printf("acd%d: sequence error (nothing to close)\n", cdp->lun);
}
+ else if (!(cdp->flags & F_WRITTEN)) {
+ cdp->flags &= ~(F_DISK_OPEN | F_TRACK_OPEN);
+ }
else {
error = acd_close_disk(cdp);
cdp->flags &= ~(F_WRITTEN | F_DISK_OPEN | F_TRACK_OPEN);
OpenPOWER on IntegriCloud