/* Subsistema de disco */ #include #include #include #include #include "Consta_DISCO.h" #include "Tipos_DISCO.h" #include "Error_DISCO.h" /* Constantes internas de implementacion */ #define ESTADO_LISTO 0 #define ESTADO_OCUPADO 1 #define ESTADO_SEEK 2 #define ESTADO_LATENC 4 #define ESTADO_TRANSF 8 #define ESTADO_RECALI 16 /* Variables globales del subsistema */ int error_disco; int discos_activos = 0; reg_tabla disc_tab[MAX_UNIDADES]; unsigned char estado[MAX_UNIDADES]; unsigned short int posicion[MAX_UNIDADES]; char flag_sistema = 0; /* funcion para posicionar el puntero del fichero de simulacion al comienzo de un sector */ off_t posiciona(reg_tabla *t, sector_logico s) { off_t desp, ret; desp = sizeof(struct parametros_disco) + s * t->pm.tamsector; ret = lseek( t->fd, desp, SEEK_SET ); if ( ret < 0 ) { error_disco = ERRDISC_EACCESO; return(-1); } return( ret ); } /* Funcion para obtener direccion fisica a partir de direccion logica de sector */ int calc_dirfisica(reg_tabla *t, sector_logico s, dir_fis *df) { int ret, resto; /* Calculo cilindro */ df->cilindro = s / t->sect_cil; resto = s % t->sect_cil; /* Calculo superficie */ df->superficie = resto / t->pm.nsectores; resto = resto % t->pm.nsectores; /* Sector */ df->sector = (unsigned short int)resto; return(0); } /*Funcion que crea un fichero de simulacion de disco */ int Inicializa_Disco(char *nombre, bloq_param desc) { int ret, t, fd, i, sectotal; char *p; sectotal = desc.nsuperficie*desc.ncilindro*desc.nsectores* desc.tamsector; if ( !sectotal || (sectotal > MAX_BYTES) ) { error_disco = ERRDISC_EFORMAT; return(-1); } fd = open(nombre, O_WRONLY|O_CREAT,0660); if ( fd < 0 ) { error_disco = ERRDISC_ENOMBRE; return(-1); } i = sizeof(bloq_param); ret = write(fd, &desc, i); if ( ret < i ) { error_disco = ERRDISC_EACCESO; return(-1); } p = (char *)malloc( desc.tamsector ); if ( p == 0 ) { error_disco = 0; return(-1); } for (i=0; i= MAX_UNIDADES ) { error_disco = ERRDISC_EDESCRI; return(-1); } if ( !flag_sistema ) { for (i=0; ifd = fd; i = sizeof(bloq_param); ret = read(fd, &p->pm, i); if ( ret < i ) { error_disco = ERRDISC_EACCESO; return(-1); } p->sect_cil = p->pm.nsuperficie * p->pm.nsectores; p->sect_disc = p->sect_cil * p->pm.ncilindro; estado[u] = ESTADO_LISTO; posicion[u] = 0; discos_activos++; return( u ); } /* Desactiva una unidad de disco */ int Desmonta_Disco(unidad u) { int ret, fd ; reg_tabla *p; if ( ( u >= MAX_UNIDADES) || ( disc_tab[u].fd < 0 ) || (discos_activos < 1) ) { error_disco = ERRDISC_EDESCRI; return(-1); } fd = close( disc_tab[u].fd ); if ( fd < 0 ) { error_disco = ERRDISC_ENOMBRE; return(-1); } disc_tab[u].fd = -1; discos_activos--; return( 0 ); } /* Devuelve el cilindro donde se encuentra el brazo */ int Lee_Posicion( unidad u ) { if ( (u >= MAX_UNIDADES) || (disc_tab[u].fd == -1) || (discos_activos < 0) ) { error_disco = ERRDISC_EDESCRI; return(-1); } return( (int)posicion[u] ); } /* Recalibra unidad */ int Recalibra_Disco( unidad u ) { tiempo t; if ( (u >= MAX_UNIDADES) || (disc_tab[u].fd == -1) || (discos_activos<0) ) { error_disco = ERRDISC_EDESCRI; return(-1); } estado[u] |= ESTADO_RECALI; t = disc_tab[u].pm.trecalib; Tiempo_Recal( t ); posicion[u] = 0; estado[u] ^= ESTADO_LISTO; return(0); } /* Posiciona el brazo de la unidad */ int Posiciona_Cabeza( unidad u, unsigned short int cil ) { tiempo t; long s, ms; unsigned short int k; if ( ( u >= MAX_UNIDADES) || (disc_tab[u].fd == -1) || (discos_activos<0) ) { error_disco = ERRDISC_EDESCRI; return(-1); } if ( cil >= disc_tab[u].pm.ncilindro ) { error_disco = ERRDISC_EDIRECC; return(-1); } estado[u] |= ESTADO_SEEK; s = disc_tab[u].pm.tseek.seg; ms = disc_tab[u].pm.tseek.mseg; if ( posicion[u] > cil ) k = posicion[u] - cil; else k = cil - posicion[u]; t.seg = k*s; t.mseg = k*ms; printf("TIEMPO DE SEEK: %ld %ld\n", t.seg, t.mseg); Tiempo_Seek( t ) ; /* simulamos tiempo de seek */ posicion[u] = cil; estado[u] ^= ESTADO_SEEK; return(0); } /* Transferencia fisica de un sector: lectura/escritura sobre el fichero simulacion */ int Transferencia_Fisica(unidad u, dir_fis direc, void *buff, int modo) { int i, ret, fd, tam, byte_registro; long registro, pos, s, ms; tiempo t; int (*transf)(); /* Test de unidad valida */ if ( (u >= MAX_UNIDADES) || (disc_tab[u].fd < 0) || (discos_activos<0) ) { error_disco = ERRDISC_EDESCRI; return(-1); } /* Test de direccion fisica valida */ if ( (direc.cilindro>=disc_tab[u].pm.ncilindro) || (direc.superficie>=disc_tab[u].pm.nsuperficie) || (direc.sector>=disc_tab[u].pm.nsectores) ) { error_disco = ERRDISC_EDIRECC; return(-1); } /* Test de modo de transferencia valido */ if ( modo == LECTURA ) transf = read; else if ( modo == ESCRITURA ) transf = write; else { error_disco = ERRDISC_EMODO; return(-1); } tam = disc_tab[u].pm.tamsector; registro = direc.cilindro*disc_tab[u].sect_cil+direc.superficie* disc_tab[u].pm.nsectores+direc.sector; byte_registro = sizeof(bloq_param) + registro*tam; fd = disc_tab[u].fd; pos = lseek(fd, (off_t)byte_registro, SEEK_SET); if ( pos < 0 ) { error_disco = ERRDISC_EACCESO; return(-1); } estado[u] |= ESTADO_LATENC; t.seg = (long)direc.sector * disc_tab[u].pm.tlatency.seg; t.mseg = (long)direc.sector * disc_tab[u].pm.tlatency.mseg; printf("Tiempo de latencia: %ld %ld\n", t.seg, t.mseg); Tiempo_Late( t ); /* Simulamos tiempo de latencia */ estado[u] ^= ESTADO_LATENC; estado[u] |= ESTADO_TRANSF; t.seg = disc_tab[u].pm.ttransf.seg; t.mseg = disc_tab[u].pm.ttransf.mseg; printf("Tiempo de transferencia: %ld %ld\n", t.seg, t.mseg); Tiempo_Transf( t ) ; /* Simulamos tiempo de transferencia */ ret = (*transf)( fd, buff, tam ); if ( ret < tam ) { error_disco = ERRDISC_EACCESO; return(-1); } estado[u] |= ESTADO_TRANSF; return(0); } /* Funcion de transferencia lgica */ int Transfiere_Sector(unidad u, sector_logico sect, void *buff, int modo) { dir_fis df; int ret; int calcula_dirfisica( reg_tabla *t, sector_logico s, dir_fis *df); /* Test de unidad valida */ if ( (u > MAX_UNIDADES) || (disc_tab[u].fd < 0) || (discos_activos<0) ) { error_disco = ERRDISC_EDESCRI; return(-1); } /* Test de direccion valida */ if ( disc_tab[u].sect_disc <= sect ) { error_disco = ERRDISC_EDIRECC; return(-1); } if ( calc_dirfisica( disc_tab + u, sect, &df ) < 0 ) { return(-1); } ret = Posiciona_Cabeza( u, df.cilindro ); if ( Transferencia_Fisica( u, df, buff, modo ) < 0 ) { return(-1); } return(0); }