Esempio n. 1
0
int loop_until_writes_done(void)
{
    TRACE_FUN(5, "loop_until_writes_done");
    int i;
    int result = 0;

    /*
     *  Wait until all data is actually written to tape.
     */
    while (ftape_state == writing && buffer[head].status != done) {
        TRACEx2(7, "tail: %d, head: %d", tail, head);
        for (i = 0; i < NR_BUFFERS; ++i) {
            TRACEx3(8, "buffer[ %d] segment_id: %d, status: %d",
                    i, buffer[i].segment_id, buffer[i].status);
        }
        result = fdc_interrupt_wait(5 * SECOND);
        if (result < 0) {
            TRACE(1, "fdc_interrupt_wait failed");
            last_write_failed = 1;
            break;
        }
        if (buffer[head].status == error) {
            /* Allow escape from loop when signaled !
             */
            if (current->signal & _DONT_BLOCK) {
                TRACE(2, "interrupted by signal");
                TRACE_EXIT;
                result = -EINTR;	/* is this the right return value ? */
                break;
            }
            if (buffer[head].hard_error_map != 0) {
                /*  Implement hard write error recovery here
                 */
            }
            buffer[head].status = waiting;	/* retry this one */
            if (runner_status == aborting) {
                ftape_dumb_stop();
                runner_status = idle;
            }
            if (runner_status != idle) {
                TRACE(1, "unexpected state: runner_status != idle");
                result = -EIO;
                break;
            }
            start_writing(WRITE_MULTI);
        }
        TRACE(5, "looping until writes done");
        result = 0;	/* normal exit status */
    }
    TRACE_EXIT;
    return result;
}
Esempio n. 2
0
static void print_error_cause(int cause)
{
	TRACE_FUN(8, "print_error_cause");

	switch (cause) {
	case no_data_error:
		TRACE(4, "no data error");
		break;
	case id_am_error:
		TRACE(4, "id am error");
		break;
	case id_crc_error:
		TRACE(4, "id crc error");
		break;
	case data_am_error:
		TRACE(4, "data am error");
		break;
	case data_crc_error:
		TRACE(4, "data crc error");
		break;
	case overrun_error:
		TRACE(4, "overrun error");
		break;
	default:
	}
	TRACE_EXIT;
}

static char *
get_fdc_mode_text(fdc_mode_enum fdc_mode)
{
	switch (fdc_mode) {
	case fdc_idle:
		return "fdc_idle";
	case fdc_reading_data:
		return "fdc_reading_data";
	case fdc_seeking:
		return "fdc_seeking";
	case fdc_writing_data:
		return "fdc_writing_data";
	case fdc_reading_id:
		return "fdc_reading_id";
	case fdc_recalibrating:
		return "fdc_recalibrating";
	default:
		return "unknown";
	}
}

static void
decode_irq_cause(fdc_mode_enum fdc_mode, byte st[],
		 char **fdc_mode_txt, error_cause * cause)
{
	TRACE_FUN(8, "decode_irq_cause");

	/*  Valid st[], decode cause of interrupt.
	 */
	*fdc_mode_txt = get_fdc_mode_text(fdc_mode);
	switch (st[0] & ST0_INT_MASK) {
	case FDC_INT_NORMAL:
		TRACEx1(fdc_mode == fdc_reading_id ? 6 : 5,
			"normal completion: %s", *fdc_mode_txt);
		*cause = no_error;
		break;
	case FDC_INT_ABNORMAL:
		TRACEx1(5, "abnormal completion %s", *fdc_mode_txt);
		TRACEx3(6, "ST0: 0x%02x, ST1: 0x%02x, ST2: 0x%02x",
			st[0], st[1], st[2]);
		TRACEx4(6, "C: 0x%02x, H: 0x%02x, R: 0x%02x, N: 0x%02x",
			st[3], st[4], st[5], st[6]);
		if (st[1] & 0x01) {
			if (st[2] & 0x01) {
				*cause = data_am_error;
			} else {
				*cause = id_am_error;
			}
		} else if (st[1] & 0x20) {
			if (st[2] & 0x20) {
				*cause = data_crc_error;
			} else {
				*cause = id_crc_error;
			}
		} else if (st[1] & 0x04) {
			*cause = no_data_error;
		} else if (st[1] & 0x10) {
			*cause = overrun_error;
		}
		print_error_cause(*cause);
		break;
	case FDC_INT_INVALID:
		TRACEx1(5, "invalid completion %s", *fdc_mode_txt);
		*cause = no_error;
		break;
	case FDC_INT_READYCH:
		TRACEx1(5, "ready change %s", *fdc_mode_txt);
		*cause = no_error;
		break;
	default:
	}
	TRACE_EXIT;
}

static void update_history(error_cause cause)
{
	switch (cause) {
	case id_am_error:
		history.id_am_errors++;
		break;
	case id_crc_error:
		history.id_crc_errors++;
		break;
	case data_am_error:
		history.data_am_errors++;
		break;
	case data_crc_error:
		history.data_crc_errors++;
		break;
	case overrun_error:
		history.overrun_errors++;
		break;
	case no_data_error:
		history.no_data_errors++;
		break;
	default:
	}
}

static void skip_bad_sector(buffer_struct * buff)
{
	TRACE_FUN(8, "skip_bad_sector");

	/* Mark sector as soft error and skip it
	 */
	if (buff->remaining > 0) {
		++buff->sector_offset;
		++buff->data_offset;
		--buff->remaining;
		buff->ptr += SECTOR_SIZE;
		buff->bad_sector_map >>= 1;
	} else {