VirtualBox

Changeset 58724 in vbox


Ignore:
Timestamp:
Nov 17, 2015 3:32:43 PM (9 years ago)
Author:
vboxsync
Message:

BIOS: Support 64-bit LBA operation. Contributed by Maksym Sobolyev. Thank you!

Location:
trunk/src/VBox/Devices
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/ahci.c

    r58044 r58724  
    360360
    361361    ahci->abCmd[8]  = (bios_dsk->drqp.lba >> 24) & 0xff;
    362     ahci->abCmd[9]  = 0;
    363     ahci->abCmd[10] = 0;
     362    ahci->abCmd[9]  = (bios_dsk->drqp.lba >> 32) & 0xff;
     363    ahci->abCmd[10] = (bios_dsk->drqp.lba >> 40) & 0xff;
    364364    ahci->abCmd[11] = 0;
    365365
     
    525525        BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    526526
    527     DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
    528              bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
    529              bios_dsk->ahcidev[device_id].port);
     527    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
     528             bios_dsk->drqp.nsect, bios_dsk->drqp.lba,
     529             device_id, bios_dsk->ahcidev[device_id].port);
    530530
    531531    high_bits_save(bios_dsk->ahci_seg :> 0);
     
    557557        BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
    558558
    559     DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
     559    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
    560560             bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
    561561             bios_dsk->ahcidev[device_id].port);
     
    602602             bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
    603603
    604     bios_dsk->drqp.lba     = (uint32_t)length << 8;     //@todo: xfer length limit
     604    bios_dsk->drqp.lba     = length << 8;     //@todo: xfer length limit
    605605    bios_dsk->drqp.buffer  = buffer;
    606606    bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
     
    690690            if (val == 0x101)
    691691            {
    692                 uint32_t    sectors;
     692                uint64_t    sectors;
    693693                uint16_t    cylinders, heads, spt;
    694694                chs_t       lgeo;
     
    713713                sectors   = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61
    714714
    715                 /** @todo update sectors to be a 64 bit number (also lba...). */
    716715                if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
    717                     sectors = *(uint32_t *)(abBuffer+(100*2)); // words 100 to 103 (someday)
    718 
    719                 DBG_AHCI("AHCI: %ld sectors\n", sectors);
     716                    sectors = *(uint64_t *)(abBuffer+(100*2)); // words 100 to 103
     717
     718                DBG_AHCI("AHCI: 0x%llx sectors\n", sectors);
    720719
    721720                bios_dsk->ahcidev[devcount_ahci].port = u8Port;
     
    759758                    set_geom_lba(&lgeo, sectors);   /* Default EDD-style translated LBA geometry. */
    760759
    761                 BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u %lu sectors\n", devcount_ahci,
    762                         u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt, sectors);
     760                BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors\n", devcount_ahci,
     761                        u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt,
     762                        sectors);
    763763
    764764                bios_dsk->devices[hd_index].lchs = lgeo;
  • trunk/src/VBox/Devices/PC/BIOS/ata.c

    r56292 r58724  
    109109        bios_dsk->devices[device].pchs.cylinders = 0;
    110110        bios_dsk->devices[device].pchs.spt       = 0;
    111         bios_dsk->devices[device].sectors     = 0;
     111        bios_dsk->devices[device].sectors        = 0;
    112112    }
    113113
     
    207207uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
    208208{
    209     uint32_t        lba;
     209    uint64_t        lba;
    210210    uint16_t        iobase1, iobase2, blksize, mult_blk_cnt;
    211211    uint16_t        cylinder;
     
    256256        if (lba + count >= 268435456)
    257257        {
    258             sector = (lba & 0xff000000L) >> 24;
    259             cylinder = 0; /* The parameter lba is just a 32 bit value. */
     258            sector = (lba >> 24) & 0x00ff;
     259            cylinder = (lba >> 32) & 0xffff;
    260260            outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
    261261            outb(iobase1 + ATA_CB_SN, sector);
     
    460460        // Now we send a IDENTIFY command to ATA device
    461461        if (type == DSK_TYPE_ATA) {
    462             uint32_t    sectors;
     462            uint64_t    sectors;
    463463            uint16_t    cylinders, heads, spt, blksize;
    464464            chs_t       lgeo;
     
    484484
    485485            sectors   = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
    486             /** @todo update sectors to be a 64 bit number (also lba...). */
    487486            if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
    488                 sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday)
     487                sectors = *(uint64_t *)(buffer+(100*2)); // words 100 to 103
    489488            switch (device)
    490489            {
     
    595594            switch (type) {
    596595            case DSK_TYPE_ATA:
    597                 sizeinmb = bios_dsk->devices[device].sectors;
    598                 sizeinmb >>= 11;
     596                sizeinmb = (bios_dsk->devices[device].sectors >> 11);
    599597            case DSK_TYPE_ATAPI:
    600598                // Read ATA/ATAPI version
     
    683681uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
    684682{
    685     uint32_t        lba;
     683    uint64_t        lba;
    686684    char __far      *buffer;
    687685    uint16_t        iobase1, iobase2, blksize;
     
    724722        if (lba + count >= 268435456)
    725723        {
    726             sector = (lba & 0xff000000L) >> 24;
    727             cylinder = 0; /* The parameter lba is just a 32 bit value. */
     724            sector = (lba >> 24) & 0x00ff;
     725            cylinder = (lba >> 32) & 0xffff;
    728726            outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
    729727            outb(iobase1 + ATA_CB_SN, sector);
     
    837835        /* CHS addressing. */
    838836        bios_dsk->devices[device_id].blksize = n_sect * 0x200;
     837        BX_DEBUG_ATA("%s: reading %u sectors (CHS)\n", __func__, n_sect);
    839838        status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
    840839        bios_dsk->devices[device_id].blksize = 0x200;
    841840    } else {
    842841        /* LBA addressing. */
    843         if (bios_dsk->drqp.lba + n_sect >= 268435456)
     842        if (bios_dsk->drqp.lba + n_sect >= 268435456) {
     843            BX_DEBUG_ATA("%s: reading %u sector (LBA,EXT)\n", __func__, n_sect);
    844844            status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_SECTORS_EXT, n_sect);
    845         else {
     845        } else {
    846846            bios_dsk->devices[device_id].blksize = n_sect * 0x200;
     847            BX_DEBUG_ATA("%s: reading %u sector (LBA,MULT)\n", __func__, n_sect);
    847848            status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
    848849            bios_dsk->devices[device_id].blksize = 0x200;
  • trunk/src/VBox/Devices/PC/BIOS/disk.c

    r56292 r58724  
    9999 * geometry in case none was provided in CMOS.
    100100 */
    101 void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors)
     101void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors64)
    102102{
    103103    uint32_t    limit = 8257536;    /* 1024 * 128 * 63 */
     104    uint32_t    nsectors;
    104105    unsigned    heads = 255;
    105106    int         i;
    106107
     108    nsectors = (nsectors64 >> 32) ? 0xFFFFFFFFL : (uint32_t)nsectors64;
    107109    /* Start with ~4GB limit, go down to 504MB. */
    108110    for (i = 0; i < 4; ++i) {
     
    331333void BIOSCALL int13_harddisk_ext(disk_regs_t r)
    332334{
    333     uint32_t            lba;
     335    uint64_t            lba;
    334336    uint16_t            ebda_seg = read_word(0x0040,0x000E);
    335337    uint16_t            segment, offset;
     
    384386        offset  = i13_ext->offset;
    385387
    386         BX_DEBUG_INT13_HD("%s: %d sectors from lba %lu @ %04x:%04x\n", __func__,
    387                           count, i13_ext->lba1, segment, offset);
    388 
    389         // Can't use 64 bits lba
     388        // Get 64 bits lba and check
    390389        lba = i13_ext->lba2;
    391         if (lba != 0L) {
    392             BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
    393             goto int13x_fail;
    394         }
    395 
    396         // Get 32 bits lba and check
    397         lba = i13_ext->lba1;
     390        lba <<= 32;
     391        lba |= i13_ext->lba1;
     392
     393        BX_DEBUG_INT13_HD("%s: %d sectors from LBA 0x%llx @ %04x:%04x\n", __func__,
     394                          count, lba, segment, offset);
    398395
    399396        type = bios_dsk->devices[device].type;
     
    467464            dpt->spt       = npspt;
    468465            dpt->blksize   = blksize;
    469             dpt->sector_count1 = lba;   // FIXME should be Bit64
    470             dpt->sector_count2 = 0;
     466            dpt->sector_count1 = lba;
     467            dpt->sector_count2 = lba >> 32;
    471468        }
    472469
  • trunk/src/VBox/Devices/PC/BIOS/ebda.h

    r56292 r58724  
    193193    chs_t       lchs;         /* Logical CHS geometry. */
    194194    chs_t       pchs;         /* Physical CHS geometry. */
    195     uint32_t    sectors;      /* Total sector count. */
     195    uint64_t    sectors;      /* Total sector count. */
    196196} disk_dev_t;
    197197
     
    201201 */
    202202typedef struct {
    203     uint32_t    lba;                /* Starting LBA. */
     203    uint64_t    lba;                /* Starting LBA. */
    204204    void __far  *buffer;            /* Read/write data buffer pointer. */
    205205    uint8_t     dev_id;             /* Device ID; index into devices array. */
     
    318318int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
    319319
    320 extern void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors);
     320extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors);
    321321
    322322// @todo: put this elsewhere (and change/eliminate?)
  • trunk/src/VBox/Devices/PC/BIOS/print.c

    r56292 r58724  
    145145//   Supports %[format_width][length]format
    146146//   where format can be x,X,u,d,s,S,c
    147 //   and the optional length modifier is l (ell)
     147//   and the optional length modifier is l (ell, long 32-bit) or ll
     148//   (long long, 64-bit).
     149//   Only x,X work with ll
    148150//--------------------------------------------------------------------------
    149151void bios_printf(uint16_t action, const char *s, ...)
     
    190192                    put_uint(action, arg, format_width, 0);
    191193                }
     194                else if (c == 'l' && s[1] == 'l') {
     195                    uint64_t llval;
     196                    uint16_t *cp16;
     197
     198                    s += 2;
     199                    c = *s;
     200                    cp16 = (uint16_t *)&llval;
     201                    cp16[0] = arg;
     202                    cp16[1] = va_arg( args, uint16_t );
     203                    cp16[2] = va_arg( args, uint16_t );
     204                    cp16[3] = va_arg( args, uint16_t );
     205                    if (c == 'x' || c == 'X') {
     206                        if (format_width == 0)
     207                            format_width = 16;
     208                        if (c == 'x')
     209                            hexadd = 'a';
     210                        else
     211                            hexadd = 'A';
     212                        for (i=format_width-1; i>=0; i--) {
     213                            nibble =  (llval >> (i * 4)) & 0x000f;
     214                            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
     215                        }
     216                    } else {
     217                        BX_PANIC("bios_printf: unknown %ll format\n");
     218                    }
     219                }
    192220                else if (c == 'l') {
    193221                    s++;
  • trunk/src/VBox/Devices/PC/BIOS/scsi.c

    r56292 r58724  
    4949
    5050/* Command opcodes. */
     51#define SCSI_SERVICE_ACT   0x9e
    5152#define SCSI_INQUIRY       0x12
    52 #define SCSI_READ_CAPACITY 0x25
     53#define SCSI_READ_CAP_10  0x25
    5354#define SCSI_READ_10       0x28
    5455#define SCSI_WRITE_10      0x2a
     56#define SCSI_READ_CAP_16   0x10    /* Not an opcode by itself, sub-action for the "Service Action" */
     57#define SCSI_READ_16       0x88
     58#define SCSI_WRITE_16      0x8a
    5559
    5660/* Data transfer direction. */
     
    6973} cdb_rw10;
    7074
     75/* READ_16/WRITE_16 CDB layout. */
     76typedef struct {
     77    uint16_t    command;    /* Command. */
     78    uint64_t    lba;        /* LBA, MSB first! */
     79    uint32_t    nsect32;    /* Sector count, MSB first! */
     80    uint8_t     pad1;       /* Unused. */
     81    uint8_t     pad2;       /* Unused. */
     82} cdb_rw16;
     83
    7184#pragma pack()
    7285
    7386ct_assert(sizeof(cdb_rw10) == 10);
    74 
     87ct_assert(sizeof(cdb_rw16) == 16);
    7588
    7689void insb_discard(unsigned nbytes, unsigned port);
     
    94107    while (status & VBSCSI_BUSY);
    95108
    96 
    97     sizes = ((length >> 12) & 0xF0) | cbCDB;
     109    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
    98110    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    99111    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
     
    146158
    147159
    148     sizes = ((length >> 12) & 0xF0) | cbCDB;
     160    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
    149161    outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
    150162    outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE);      /* Write the transfer direction. */
     
    185197}
    186198
     199static uint64_t swap_64(uint64_t val)
     200{
     201    uint64_t rval;
     202
     203    rval = swap_32(val & 0xffffffff);
     204    rval <<= 32;
     205    rval |= swap_32(val >> 32);
     206
     207    return rval;
     208}
     209
    187210/**
    188211 * Read sectors from an attached SCSI device.
     
    195218{
    196219    uint8_t             rc;
    197     cdb_rw10            cdb;
    198     uint16_t            count;
     220    cdb_rw16            cdb;
     221    uint32_t            count;
    199222    uint16_t            io_base;
    200223    uint8_t             target_id;
     
    208231
    209232    /* Prepare a CDB. */
    210     cdb.command = SCSI_READ_10;
    211     cdb.lba     = swap_32(bios_dsk->drqp.lba);
     233    cdb.command = SCSI_READ_16;
     234    cdb.lba     = swap_64(bios_dsk->drqp.lba);
    212235    cdb.pad1    = 0;
    213     cdb.nsect   = swap_16(count);
     236    cdb.nsect32 = swap_32(count);
    214237    cdb.pad2    = 0;
    215238
     
    221244             count, device_id, bios_dsk->scsidev[device_id].target_id);
    222245
    223     rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 10,
     246    rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16,
    224247                          bios_dsk->drqp.buffer, (count * 512L));
    225248
     
    244267{
    245268    uint8_t             rc;
    246     cdb_rw10            cdb;
    247     uint16_t            count;
     269    cdb_rw16            cdb;
     270    uint32_t            count;
    248271    uint16_t            io_base;
    249272    uint8_t             target_id;
     
    257280
    258281    /* Prepare a CDB. */
    259     cdb.command = SCSI_WRITE_10;
    260     cdb.lba     = swap_32(bios_dsk->drqp.lba);
     282    cdb.command = SCSI_WRITE_16;
     283    cdb.lba     = swap_64(bios_dsk->drqp.lba);
    261284    cdb.pad1    = 0;
    262     cdb.nsect   = swap_16(count);
     285    cdb.nsect32 = swap_32(count);
    263286    cdb.pad2    = 0;
    264287
     
    269292             count, device_id, bios_dsk->scsidev[device_id].target_id);
    270293
    271     rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 10,
     294    rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16,
    272295                           bios_dsk->drqp.buffer, (count * 512L));
    273296
     
    403426    {
    404427        uint8_t     rc;
    405         uint8_t     aCDB[10];
     428        uint8_t     aCDB[16];
    406429        uint8_t     hd_index, devcount_scsi;
    407430
     
    428451            if (devcount_scsi < BX_MAX_SCSI_DEVICES)
    429452            {
    430                 uint32_t    sectors, sector_size, cylinders;
     453                uint64_t    sectors, t;
     454                uint32_t    sector_size, cylinders;
    431455                uint16_t    heads, sectors_per_track;
    432456                uint8_t     hdcount;
     
    435459                /* Issue a read capacity command now. */
    436460                _fmemset(aCDB, 0, sizeof(aCDB));
    437                 aCDB[0] = SCSI_READ_CAPACITY;
    438 
    439                 rc = scsi_cmd_data_in(io_base, i, aCDB, 10, buffer, 8);
     461                aCDB[0] = SCSI_SERVICE_ACT;
     462                aCDB[1] = SCSI_READ_CAP_16;
     463                aCDB[13] = 32; /* Allocation length. */
     464
     465                rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);
    440466                if (rc != 0)
    441467                    BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
    442468
    443                 /* Build sector number and size from the buffer. */
    444                 //@todo: byte swapping for dword sized items should be farmed out...
    445                 sectors =   ((uint32_t)buffer[0] << 24)
    446                           | ((uint32_t)buffer[1] << 16)
    447                           | ((uint32_t)buffer[2] << 8)
    448                           | ((uint32_t)buffer[3]);
    449                 ++sectors;  /* Returned value is the last LBA, zero-based. */
    450 
    451                 sector_size =   ((uint32_t)buffer[4] << 24)
    452                               | ((uint32_t)buffer[5] << 16)
    453                               | ((uint32_t)buffer[6] << 8)
    454                               | ((uint32_t)buffer[7]);
     469                /* The value returned is the last addressable LBA, not
     470                 * the size, which what "+ 1" is for.
     471                 */
     472                sectors = swap_64(*(uint64_t *)buffer) + 1;
     473
     474                sector_size =   ((uint32_t)buffer[8] << 24)
     475                              | ((uint32_t)buffer[9] << 16)
     476                              | ((uint32_t)buffer[10] << 8)
     477                              | ((uint32_t)buffer[11]);
    455478
    456479                /* We only support the disk if sector size is 512 bytes. */
     
    497520                        heads = 255;
    498521                        sectors_per_track = 63;
     522                        /* Approximate x / (255 * 63) using shifts */
     523                        t = (sectors >> 6) + (sectors >> 12);
     524                        cylinders = (t >> 8) + (t >> 16);
    499525                    }
    500526                    else if (sectors >= (uint32_t)2 * 1024 * 1024)
     
    502528                        heads = 128;
    503529                        sectors_per_track = 32;
     530                        cylinders = sectors >> 12;
    504531                    }
    505532                    else
     
    507534                        heads = 64;
    508535                        sectors_per_track = 32;
     536                        cylinders = sectors >> 11;
    509537                    }
    510                     cylinders = (uint32_t)(sectors / (heads * sectors_per_track));
    511538                }
    512539
     
    523550                bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
    524551
    525                 /* Write LCHS values. */
     552                /* Write LCHS/PCHS values. */
    526553                bios_dsk->devices[hd_index].lchs.heads = heads;
    527554                bios_dsk->devices[hd_index].lchs.spt   = sectors_per_track;
    528                 if (cylinders > 1024)
    529                     bios_dsk->devices[hd_index].lchs.cylinders = 1024;
    530                 else
    531                     bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
    532 
    533                 BX_INFO("SCSI %d-ID#%d: LCHS=%u/%u/%u %lu sectors\n", devcount_scsi,
    534                         i, (uint16_t)cylinders, heads, sectors_per_track, sectors);
    535 
    536                 /* Write PCHS values. */
    537555                bios_dsk->devices[hd_index].pchs.heads = heads;
    538556                bios_dsk->devices[hd_index].pchs.spt   = sectors_per_track;
    539                 if (cylinders > 1024)
     557
     558                if (cylinders > 1024) {
     559                    bios_dsk->devices[hd_index].lchs.cylinders = 1024;
    540560                    bios_dsk->devices[hd_index].pchs.cylinders = 1024;
    541                 else
     561                } else {
     562                    bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
    542563                    bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
     564                }
     565
     566                BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
     567                        i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
    543568
    544569                bios_dsk->devices[hd_index].sectors = sectors;
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp

    r57358 r58724  
    176176            {
    177177                uint8_t cbCDB = uVal & 0x0F;
     178
     179                if (cbCDB == 0)
     180                    cbCDB = 16;
    178181                if (cbCDB > VBOXSCSI_CDB_SIZE_MAX)
    179182                    vboxscsiReset(pVBoxSCSI, true /*fEverything*/);
  • trunk/src/VBox/Devices/Storage/VBoxSCSI.h

    r56427 r58724  
    8888
    8989/** Maximum CDB size the BIOS driver sends. */
    90 #define VBOXSCSI_CDB_SIZE_MAX     10
     90#define VBOXSCSI_CDB_SIZE_MAX     16
    9191
    9292typedef struct VBOXSCSI
     
    101101    uint8_t              cbCDB;
    102102    /** The command to issue. */
    103     uint8_t              abCDB[12];
     103    uint8_t              abCDB[VBOXSCSI_CDB_SIZE_MAX + 4];
    104104    /** Current position in the array. */
    105105    uint8_t              iCDB;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette