//////////////////////////////////////////////////////////// // Push down any data from the old tree onto the new tree // by doing a traversal over the deleted clusters ////////////////////////////////////////////////////////// void pushDown(cluster* cl) { cluster* ccl; int i; assert(cl); ccl = GET_CL(cl); deprintf("pushDown: cl = %d\n",ccl->id); cluster** clusters = ccl->getClusters(); for(i=0; i < MAX_DEGREE; ++i) { cluster* child = clusters[i]; cluster* ccp = GET_CL(child); if(child) { pushDownFun(ccl,ccp); if(isDeleted(ccp)) { if(ccp->child) { deprintf("Child\n"); pushDown(child); deprintf("ret\n"); } freeCluster(ccp); } } } free(clusters); }
void setupNullaryVertexCluster (node* thisNode, int event, tree_t* tree, clusterList* rootList) { int i, k=0; unary_cluster *cll; final_cluster *cl = new (allocBlock(tree->UClusters)) final_cluster; drun(ucs++); cluster* oldCluster = thisNode->vertex->cl; if(oldCluster != NULL) { if(PUSHDOWN) { oldCluster->affected = DELETED; if(isRoot(oldCluster)) insertCluster(oldCluster,rootList); } else { freeVertexCluster(oldCluster,tree); } } thisNode->vertex->cl = cl; deprintf("Setting up cluster for node %d\n",thisNode->nId); deprintf("Cluster %p\n",cl); cl->id = thisNode->nId; cl->height = thisNode->height; // Make children cluster points to thisNode for(i = 0; i < MAX_DEGREE; i++) { cll = (unary_cluster *) GET_CL(thisNode->scars[i].cl); deprintf("i is %d \n",i); if(cll) { deprintf("cll exists\n"); cll->parent = cl; cl->unaryCl[k] = (unary_cluster *) thisNode->scars[i].cl; deprintf("Unary cluster %d is %p\n", k, cl->unaryCl[k]); k++; } } for(k=k;k<MAX_DEGREE;k++) { cl->unaryCl[k] = NULL; } // Make node data cluster points to this node cll = thisNode->data; cll->parent = cl; cl->child = cll; deprintf("Cl->id is %d\n",cl->id); }
void setupBinVertexCluster (node* thisNode, int event,tree_t* tree, clusterList* rootList) { int i, j=0,k=0; cluster *cll; bin_cluster *cl; cluster* oldCluster = thisNode->vertex->cl; cl = new (allocBlock(tree->BClusters)) bin_cluster; drun(bcs++); if(oldCluster != NULL) { if(PUSHDOWN) { oldCluster->affected = DELETED; if(isRoot(oldCluster)) insertCluster(oldCluster,rootList); } else { freeVertexCluster(oldCluster,tree); } } thisNode->vertex->cl = cl; deprintf("Setting up binary cluster %p\n",cl); cl->id = thisNode->nId; cl->height = thisNode->height; // Make children cluster points to thisNode for(i = 0; i < MAX_DEGREE; i++) { cll = (cluster *) GET_CL(thisNode->scars[i].cl); if(cll) { cll->parent = cl; if(i == thisNode->left || i == thisNode->right) { cl->binaryCl[j] = (bin_cluster *) thisNode->scars[i].cl; j++; } else { cl->unaryCl[k] = (unary_cluster *) thisNode->scars[i].cl; k++; } } } for(k=k;k<MAX_DEGREE-2;k++) { cl->unaryCl[k] = NULL; } // Make node data cluster points to this node cll = thisNode->data; cll->parent = cl; cl->child = cll; }
/* Find the clusters with the two largest distances from the distinguished endpints, adjusting for being in a subcluster */ void find2max(cluster* curcl, cluster** child, double* max2,int ep1,double w1,int ep2,double w2) { int i; double max1; double effMax; bin_cluster** binaryCl; unary_cluster** unaryCl; max1 = *max2 = 0; binaryCl = (bin_cluster**) curcl->getBinaryClusters(); unaryCl = (unary_cluster**) curcl->getUnaryClusters(); for (i = 0; i < curcl->endpoints; ++i) { bin_cluster* cl = binaryCl[i]; if(cl) { bin_data* d = getBinData(cl); double mpath = getThisData(d); double len = getLen(d); deprintf("Binary cluster \n"); if((GET_CL(cl))->isEndPoint(ep1)) effMax = dmax(mpath,w1+len); else effMax = dmax(mpath,w2+len); deprintf("mpath is %lf, len is %lf \n",mpath, len); deprintf("w1 is %lf, w2 is %lf, ep1 is %d, ep2 is %d\n",w1,w2,ep1,ep2); deprintf("i is %d, effMax is %lf, max1 is %lf\n", i, effMax,max1); if(effMax > max1) {*max2 = max1; *child = cl; max1 = effMax;} else if(effMax > *max2) {*max2 = effMax;} } } for(i=0;i<MAX_DEGREE-curcl->endpoints;i++) { unary_cluster* cl = unaryCl[i]; if(cl) { double mpath = cl->data.mpath; effMax = mpath; deprintf("i is %d, effMax is %lf, max1 is %lf\n", i, effMax,max1); if(effMax > max1) {*max2 = max1; *child = cl; max1 = effMax;} else if(effMax > *max2) {*max2 = effMax;} } } }
cluster* synchronizeClusterContract(cluster* cl) { int i; cluster** clusters = cl->getClusters(); for(i=0; i < MAX_DEGREE; ++i) { if(clusters[i]) { cluster* ccp = GET_CL(clusters[i]); deprintf("Child->affected is %d\n",ccp->affected); if(ccp->affected == IS_AFFECTED) { synchronizeClusterContract(ccp); } } } free(clusters); updateClusterContract(cl); return cl; }
void BIOSCALL int13_cdemu(disk_regs_t r) { // @TODO: a macro or a function for getting the EBDA segment uint16_t ebda_seg=read_word(0x0040,0x000E); uint8_t device, status; uint16_t vheads, vspt, vcylinders; uint16_t head, sector, cylinder, nbsectors; uint32_t vlba, ilba, slba, elba; uint16_t before, segment, offset; cdb_atapi atapicmd; cdemu_t __far *cdemu; bio_dsk_t __far *bios_dsk; cdemu = ebda_seg :> &EbdaData->cdemu; bios_dsk = ebda_seg :> &EbdaData->bdisk; BX_DEBUG_INT13_ET("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES); /* at this point, we are emulating a floppy/harddisk */ // Recompute the device number device = cdemu->controller_index * 2; device += cdemu->device_spec; SET_DISK_RET_STATUS(0x00); /* basic checks : emulation should be active, dl should equal the emulated drive */ if (!cdemu->active || (cdemu->emulated_drive != GET_DL())) { BX_INFO("%s: function %02x, emulation not active for DL= %02x\n", __func__, GET_AH(), GET_DL()); goto int13_fail; } switch (GET_AH()) { case 0x00: /* disk controller reset */ if (pktacc[bios_dsk->devices[device].type]) { status = softrst[bios_dsk->devices[device].type](device); } goto int13_success; break; // all those functions return SUCCESS case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ? case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ? case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ case 0x16: /* detect disk change */ goto int13_success; break; // all those functions return disk write-protected case 0x03: /* write disk sectors */ case 0x05: /* format disk track */ SET_AH(0x03); goto int13_fail_noah; break; case 0x01: /* read disk status */ status=read_byte(0x0040, 0x0074); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; break; case 0x02: // read disk sectors case 0x04: // verify disk sectors vspt = cdemu->vdevice.spt; vcylinders = cdemu->vdevice.cylinders; vheads = cdemu->vdevice.heads; ilba = cdemu->ilba; sector = GET_CL() & 0x003f; cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH(); head = GET_DH(); nbsectors = GET_AL(); segment = ES; offset = BX; BX_DEBUG_INT13_ET("%s: read to %04x:%04x @ VCHS %u/%u/%u (%u sectors)\n", __func__, ES, BX, cylinder, head, sector, nbsectors); // no sector to read ? if(nbsectors==0) goto int13_success; // sanity checks sco openserver needs this! if ((sector > vspt) || (cylinder >= vcylinders) || (head >= vheads)) { goto int13_fail; } // After validating the input, verify does nothing if (GET_AH() == 0x04) goto int13_success; segment = ES+(BX / 16); offset = BX % 16; // calculate the virtual lba inside the image vlba=((((uint32_t)cylinder*(uint32_t)vheads)+(uint32_t)head)*(uint32_t)vspt)+((uint32_t)(sector-1)); // In advance so we don't lose the count SET_AL(nbsectors); // start lba on cd slba = (uint32_t)vlba / 4; before = (uint32_t)vlba % 4; // end lba on cd elba = (uint32_t)(vlba + nbsectors - 1) / 4; _fmemset(&atapicmd, 0, sizeof(atapicmd)); atapicmd.command = 0x28; // READ 10 command atapicmd.lba = swap_32(ilba + slba); atapicmd.nsect = swap_16(elba - slba + 1); bios_dsk->drqp.nsect = nbsectors; bios_dsk->drqp.sect_sz = 512; bios_dsk->drqp.skip_b = before * 512; bios_dsk->drqp.skip_a = ((4 - nbsectors % 4 - before) * 512) % 2048; status = pktacc[bios_dsk->devices[device].type](device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset)); bios_dsk->drqp.skip_b = 0; bios_dsk->drqp.skip_a = 0; if (status != 0) { BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status); SET_AH(0x02); SET_AL(0); goto int13_fail_noah; } goto int13_success; break; case 0x08: /* read disk drive parameters */ vspt = cdemu->vdevice.spt; vcylinders = cdemu->vdevice.cylinders - 1; vheads = cdemu->vdevice.heads - 1; SET_AL( 0x00 ); SET_BL( 0x00 ); SET_CH( vcylinders & 0xff ); SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt & 0x3f )); SET_DH( vheads ); SET_DL( 0x02 ); // FIXME ElTorito Various. should send the real count of drives 1 or 2 // FIXME ElTorito Harddisk. should send the HD count switch (cdemu->media) { case 0x01: SET_BL( 0x02 ); break; /* 1.2 MB */ case 0x02: SET_BL( 0x04 ); break; /* 1.44 MB */ case 0x03: SET_BL( 0x05 ); break; /* 2.88 MB */ } /* Only set the DPT pointer for emulated floppies. */ if (cdemu->media < 4) { DI = (uint16_t)&diskette_param_table; // @todo: should this depend on emulated medium? ES = 0xF000; // @todo: how to make this relocatable? } goto int13_success; break; case 0x15: /* read disk drive size */ // FIXME ElTorito Harddisk. What geometry to send ? SET_AH(0x03); goto int13_success_noah; break; // all those functions return unimplemented case 0x0a: /* read disk sectors with ECC */ case 0x0b: /* write disk sectors with ECC */ case 0x18: /* set media type for format */ case 0x41: // IBM/MS installation check // FIXME ElTorito Harddisk. Darwin would like to use EDD case 0x42: // IBM/MS extended read case 0x43: // IBM/MS extended write case 0x44: // IBM/MS verify sectors case 0x45: // IBM/MS lock/unlock drive case 0x46: // IBM/MS eject media case 0x47: // IBM/MS extended seek case 0x48: // IBM/MS get drive parameters case 0x49: // IBM/MS extended media change case 0x4e: // ? - set hardware configuration case 0x50: // ? - send packet command default: BX_INFO("%s: function AH=%02x unsupported, returns fail\n", __func__, GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter int13_fail_noah: SET_DISK_RET_STATUS(GET_AH()); int13_fail_nostatus: SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error int13_success_noah: SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error return; }
void BIOSCALL int13_harddisk(disk_regs_t r) { uint32_t lba; uint16_t cylinder, head, sector; uint16_t nlc, nlh, nlspt; uint16_t count; uint8_t device, status; bio_dsk_t __far *bios_dsk; BX_DEBUG_INT13_HD("%s: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", __func__, AX, BX, CX, DX, ES); bios_dsk = read_word(0x0040,0x000E) :> &EbdaData->bdisk; write_byte(0x0040, 0x008e, 0); // clear completion flag // basic check : device has to be defined if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_STORAGE_DEVICES) ) { BX_DEBUG("%s: function %02x, ELDL out of range %02x\n", __func__, GET_AH(), GET_ELDL()); goto int13_fail; } // Get the ata channel device = bios_dsk->hdidmap[GET_ELDL()-0x80]; // basic check : device has to be valid if (device >= BX_MAX_STORAGE_DEVICES) { BX_DEBUG("%s: function %02x, unmapped device for ELDL=%02x\n", __func__, GET_AH(), GET_ELDL()); goto int13_fail; } switch (GET_AH()) { case 0x00: /* disk controller reset */ #ifdef VBOX_WITH_SCSI /* SCSI controller does not need a reset. */ if (!VBOX_IS_SCSI_DEVICE(device)) #endif ata_reset (device); goto int13_success; break; case 0x01: /* read disk status */ status = read_byte(0x0040, 0x0074); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; break; case 0x02: // read disk sectors case 0x03: // write disk sectors case 0x04: // verify disk sectors count = GET_AL(); cylinder = GET_CH(); cylinder |= ( ((uint16_t) GET_CL()) << 2) & 0x300; sector = (GET_CL() & 0x3f); head = GET_DH(); /* Segment and offset are in ES:BX. */ if ( (count > 128) || (count == 0) ) { BX_INFO("%s: function %02x, count out of range!\n", __func__, GET_AH()); goto int13_fail; } /* Get the logical CHS geometry. */ nlc = bios_dsk->devices[device].lchs.cylinders; nlh = bios_dsk->devices[device].lchs.heads; nlspt = bios_dsk->devices[device].lchs.spt; /* Sanity check the geometry. */ if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) { BX_INFO("%s: function %02x, disk %02x, parameters out of range %04x/%04x/%04x!\n", __func__, GET_AH(), GET_DL(), cylinder, head, sector); goto int13_fail; } // FIXME verify if ( GET_AH() == 0x04 ) goto int13_success; /* If required, translate LCHS to LBA and execute command. */ //@todo: The IS_SCSI_DEVICE check should be redundant... if (( (bios_dsk->devices[device].pchs.heads != nlh) || (bios_dsk->devices[device].pchs.spt != nlspt)) || VBOX_IS_SCSI_DEVICE(device)) { lba = ((((uint32_t)cylinder * (uint32_t)nlh) + (uint32_t)head) * (uint32_t)nlspt) + (uint32_t)sector - 1; sector = 0; // this forces the command to be lba } /* Clear the count of transferred sectors/bytes. */ bios_dsk->drqp.trsfsectors = 0; bios_dsk->drqp.trsfbytes = 0; /* Pass request information to low level disk code. */ bios_dsk->drqp.lba = lba; bios_dsk->drqp.buffer = MK_FP(ES, BX); bios_dsk->drqp.nsect = count; bios_dsk->drqp.sect_sz = 512; //@todo: device specific? bios_dsk->drqp.cylinder = cylinder; bios_dsk->drqp.head = head; bios_dsk->drqp.sector = sector; bios_dsk->drqp.dev_id = device; status = dskacc[bios_dsk->devices[device].type].a[GET_AH() - 0x02](bios_dsk); // Set nb of sector transferred SET_AL(bios_dsk->drqp.trsfsectors); if (status != 0) { BX_INFO("%s: function %02x, error %02x !\n", __func__, GET_AH(), status); SET_AH(0x0c); goto int13_fail_noah; } goto int13_success; break; case 0x05: /* format disk track */ BX_INFO("format disk track called\n"); goto int13_success; return; break; case 0x08: /* read disk drive parameters */ /* Get the logical geometry from internal table. */ nlc = bios_dsk->devices[device].lchs.cylinders; nlh = bios_dsk->devices[device].lchs.heads; nlspt = bios_dsk->devices[device].lchs.spt; count = bios_dsk->hdcount; /* Maximum cylinder number is just one less than the number of cylinders. */ nlc = nlc - 1; /* 0 based , last sector not used */ SET_AL(0); SET_CH(nlc & 0xff); SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f)); SET_DH(nlh - 1); SET_DL(count); /* FIXME returns 0, 1, or n hard drives */ // FIXME should set ES & DI // @todo: Actually, the above comment is nonsense. goto int13_success; break; case 0x10: /* check drive ready */ // should look at 40:8E also??? // Read the status from controller status = inb(bios_dsk->channels[device/2].iobase1 + ATA_CB_STAT); if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) { goto int13_success; } else { SET_AH(0xAA); goto int13_fail_noah; } break; case 0x15: /* read disk drive size */ /* Get the physical geometry from internal table. */ cylinder = bios_dsk->devices[device].pchs.cylinders; head = bios_dsk->devices[device].pchs.heads; sector = bios_dsk->devices[device].pchs.spt; /* Calculate sector count seen by old style INT 13h. */ lba = (uint32_t)cylinder * head * sector; CX = lba >> 16; DX = lba & 0xffff; SET_AH(3); // hard disk accessible goto int13_success_noah; break; case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ BX_INFO("%s: function %02xh unimplemented, returns success\n", __func__, GET_AH()); goto int13_success; break; case 0x0a: /* read disk sectors with ECC */ case 0x0b: /* write disk sectors with ECC */ case 0x18: // set media type for format default: BX_INFO("%s: function %02xh unsupported, returns fail\n", __func__, GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter int13_fail_noah: SET_DISK_RET_STATUS(GET_AH()); int13_fail_nostatus: SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error int13_success_noah: SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error return; }
int traverse(cluster* curcl, int ep1, double w1, int ep2, double w2) { double max2; //data_t* dat; cluster* child=NULL; cluster* cll = NULL; cluster* cl2 = GET_CL(curcl); // printf ("!"); deprintf("Traverse: %d \n",cl2->id); find2max(curcl, &child, &max2,ep1,w1,ep2,w2); child = GET_CL(child); cll = GET_CL(child); switch(curcl->endpoints) { case 0: deprintf("End Event\n"); if(child) { deprintf("max2 is %lf\n",max2);//dat= thisData(child); //deprintf("max is %lf\n",dat->mpath); cll= GET_CL(child); if(cll->child) return traverse(child,curcl->id,max2, -1, -1.0); else assert(0); } else return curcl->id; break; case 1: deprintf("Rake event\n"); if(cll->endpoints == 2) { if(cll->child) return traverse(child,curcl->id,max2,ep1,w1); else { deprintf("ep1 is %d \n",ep1); deprintf("max2 is %lf \n",max2); deprintf("w1 is %lf \n",w1); if(w1 > max2) return ep1; else return curcl->id; } } else if(child->child) return traverse(child,curcl->id,max2,-1,-1.0); else { deprintf("child->child is %p\n",child->child); deprintf("child is %p\n",child); drun(CRASH);//assert(0); } case 2: deprintf("Compress Event\n"); if(child->endpoints == 2) { deprintf("Binary Child\n"); if(child->child) { deprintf("with children\n");drun(fflush(stdout)); if(child->isEndPoint(ep1)) { deprintf("Ep1 is an endpoint \n"); return traverse(child,ep1,w1,curcl->id,max2); } else { deprintf("ep2 is an endpoint\n"); return traverse(child,ep2,w2,curcl->id,max2); } } else { deprintf("no children\n"); deprintf("child is %p\n",child); if(child->isEndPoint(ep1)) { deprintf("ep1 is an endpoint\n");drun(fflush(stdout)); if(w1 > max2) return ep1; else return curcl->id; } else { deprintf("ep2 is an endpoint\n");drun(fflush(stdout)); if(w2 > max2) return ep2; else return curcl->id; } } } else { if(child->child) return traverse(child,curcl->id,max2,-1,-1.0); else assert(0); } default: assert(0); } }
///////////////////////////////////////////////////////////////////// // doLive (for the initial run in the inintial run if the node // is going to live then copy down the neighbor's scars associated // with the node, and copy down the empty scars for the node //////////////////////////////////////////////////////////////////// void doLive(node* thisNode) { int i,new_degree; int neighs[MAX_DEGREE]; node* neigh; node* desc; scar *neigh_scar, *desc_scar; drun(intptr_t j); drun(cluster* cl); neighs[0]=-1;neighs[1]=-1; deprintf("I live!!! I am %d\n",thisNode->nId); drun(deprintf("Degree is %d\n",thisNode->degree)); // Compute degree, remember left and right new_degree = 0; for(i=0;i<MAX_DEGREE;i++) { neigh_scar = thisNode->scars[i].backscar; if (neigh_scar) { neigh = GET_NEIGHBOR(neigh_scar); deprintf("i is %d\n",i); if(neigh->degree > 1) { neighs[new_degree] = i; ++new_degree; } } } desc = thisNode->descendant; desc->degree = new_degree; desc->left = neighs[0]; desc->right = neighs[1]; // copy node data and your neighbors scars down to the next level desc->data = thisNode->data; for(i=0;i<MAX_DEGREE; i++) { neigh_scar = thisNode->scars[i].backscar; if (neigh_scar) { neigh = GET_NEIGHBOR(neigh_scar); desc_scar= (scar *) ((intptr_t)neigh->descendant+ (intptr_t) neigh_scar - (intptr_t)neigh); desc_scar->cl = neigh_scar->cl; desc_scar->backscar = desc->scars+i; deprintf("Wrote %p at address %p\n",desc,GET_NEIGHBOR(desc_scar->backscar)); } else { // no neighbor: just copy this scar down desc->scars[i].cl = thisNode->scars[i].cl; desc->scars[i].backscar = NULL; drun(j= (intptr_t) thisNode->scars->cl & 3); drun(cl = GET_CL(thisNode->scars[i].cl)); drun(deprintf("the cl is %p\n", cl)); } } }