diff --git a/drivers/at_wini/at_wini.c b/drivers/at_wini/at_wini.c index f108cb959..78d077229 100644 --- a/drivers/at_wini/at_wini.c +++ b/drivers/at_wini/at_wini.c @@ -16,6 +16,7 @@ #include "at_wini.h" #include #include +#include #if ENABLE_AT_WINI @@ -140,6 +141,8 @@ struct command { /* Some controllers don't interrupt, the clock will wake us up. */ #define WAKEUP (32*HZ) /* drive may be out for 31 seconds max */ +int wakeup_ticks = WAKEUP; + /* Miscellaneous. */ #define MAX_DRIVES 4 /* this driver supports 4 drives (d0 - d3) */ #if _WORD_SIZE > 2 @@ -153,8 +156,7 @@ struct command { #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) #define DELAY_USECS 1000 /* controller timeout in microseconds */ #define DELAY_TICKS 1 /* controller timeout in ticks */ -#define TIMEOUT_USECS 5000000 /* controller timeout in microseconds */ -#define TIMEOUT_TICKS 300 /* controller timeout in ticks */ +#define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks */ #define RECOVERY_USECS 500000 /* controller recovery time in microseconds */ #define RECOVERY_TICKS 30 /* controller recovery time in ticks */ #define INITIALIZED 0x01 /* drive is initialized */ @@ -166,6 +168,7 @@ struct command { #define ATAPI 0 /* don't bother with ATAPI; optimise out */ #endif +int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS; /* Variables. */ PRIVATE struct wini { /* main drive struct, one entry per drive */ @@ -205,6 +208,7 @@ FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position, FORWARD _PROTOTYPE( int com_out, (struct command *cmd) ); FORWARD _PROTOTYPE( void w_need_reset, (void) ); FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) ); +FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) ); FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) ); FORWARD _PROTOTYPE( void w_timeout, (void) ); FORWARD _PROTOTYPE( int w_reset, (void) ); @@ -237,7 +241,7 @@ PRIVATE struct driver w_dtab = { nop_fkey, nop_cancel, nop_select, - NULL + w_other /* catch-all for unrecognized commands and ioctls */ }; @@ -640,7 +644,7 @@ unsigned nr_req; /* length of request vector */ /* Any errors? */ if (r != OK) { /* Don't retry if sector marked bad or too many errors. */ - if (r == ERR_BAD_SECTOR || ++errors == MAX_ERRORS) { + if (r == ERR_BAD_SECTOR || ++errors == max_errors) { w_command = CMD_IDLE; return(EIO); } @@ -685,7 +689,7 @@ struct command *cmd; /* Command block */ * controller was not able to execute the command. Leftover timeouts are * simply ignored by the main loop. */ - sys_syncalrm(SELF, WAKEUP, 0); + sys_syncalrm(SELF, wakeup_ticks, 0); w_status = STATUS_ADMBSY; w_command = cmd->command; @@ -894,7 +898,7 @@ int value; /* required status */ if ((w_status & mask) == value) { return 1; } - } while ((s=getuptime(&t1)) == OK && (t1-t0) < TIMEOUT_TICKS ); + } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks ); if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s); w_need_reset(); /* controller gone deaf */ @@ -1064,7 +1068,7 @@ unsigned nr_req; /* length of request vector */ if (r < 0) { err: /* Don't retry if too many errors. */ - if (++errors == MAX_ERRORS) { + if (++errors == max_errors) { w_command = CMD_IDLE; return(EIO); } @@ -1103,7 +1107,7 @@ unsigned cnt; * controller was not able to execute the command. Leftover timeouts are * simply ignored by the main loop. */ - sys_syncalrm(SELF, WAKEUP, 0); + sys_syncalrm(SELF, wakeup_ticks, 0); #if _WORD_SIZE > 2 if (cnt > 0xFFFE) cnt = 0xFFFE; /* Max data per interrupt. */ @@ -1131,6 +1135,39 @@ unsigned cnt; return(OK); } +/*============================================================================* + * w_other * + *============================================================================*/ +PRIVATE int w_other(dr, m) +struct driver *dr; +message *m; +{ + int r, timeout, prev; + + if(m->m_type != DEV_IOCTL || m->REQUEST != DIOCTIMEOUT) + return EINVAL; + + if((r=sys_datacopy(m->PROC_NR, (vir_bytes)m->ADDRESS, + SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK) + return r; + + if(timeout < 1) + return EINVAL; + + prev = wakeup_ticks; + wakeup_ticks = timeout; + if(timeout_ticks > timeout) + timeout_ticks = timeout; + + if((r=sys_datacopy(SELF, (vir_bytes)&prev, + m->PROC_NR, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK) + return r; + + max_errors = 2; + + return OK; +} + /*============================================================================* * atapi_intr_wait * *============================================================================*/ diff --git a/drivers/libdriver/driver.c b/drivers/libdriver/driver.c index adedb0a27..bfd360e62 100644 --- a/drivers/libdriver/driver.c +++ b/drivers/libdriver/driver.c @@ -375,7 +375,11 @@ message *mp; /* pointer to ioctl request */ struct partition entry; int s; - if (mp->REQUEST != DIOCSETP && mp->REQUEST != DIOCGETP) return(ENOTTY); + if (mp->REQUEST != DIOCSETP && mp->REQUEST != DIOCGETP) { + if(dp->dr_other) { + return dp->dr_other(dp, mp); + } else return(ENOTTY); + } /* Decode the message parameters. */ if ((dv = (*dp->dr_prepare)(mp->DEVICE)) == NIL_DEV) return(ENXIO); diff --git a/drivers/libdriver/drvlib.c b/drivers/libdriver/drvlib.c index b5fef949d..82b68f6ec 100644 --- a/drivers/libdriver/drvlib.c +++ b/drivers/libdriver/drvlib.c @@ -14,7 +14,7 @@ FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev, unsigned long extbase) ); FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device, - unsigned long offset, struct part_entry *table) ); + unsigned long offset, struct part_entry *table, int *io) ); FORWARD _PROTOTYPE( int get_iso_fake_part_table, (struct driver *dp, int device, unsigned long offset, struct part_entry *table) ); FORWARD _PROTOTYPE( void sort, (struct part_entry *table) ); @@ -36,7 +36,7 @@ int style; /* partitioning style: floppy, primary, sub. */ * systems that expect this. */ struct part_entry table[NR_PARTITIONS], *pe; - int disk, par; + int disk, par, io; struct device *dv; unsigned long base, limit, part_limit; @@ -47,8 +47,8 @@ int style; /* partitioning style: floppy, primary, sub. */ limit = base + div64u(dv->dv_size, SECTOR_SIZE); /* Read the partition table for the device. */ - if (!get_part_table(dp, device, 0L, table)) - if(!get_iso_fake_part_table(dp, device, 0L, table)) + if (!get_part_table(dp, device, 0L, table, &io)) + if(!io || !get_iso_fake_part_table(dp, device, 0L, table)) return; /* Compute the device number of the first partition. */ @@ -116,7 +116,7 @@ unsigned long extbase; /* sector offset of the base extended partition */ offset = 0; do { - if (!get_part_table(dp, extdev, offset, table)) return; + if (!get_part_table(dp, extdev, offset, table, NULL)) return; sort(table); /* The table should contain one logical partition and optionally @@ -146,11 +146,12 @@ unsigned long extbase; /* sector offset of the base extended partition */ /*============================================================================* * get_part_table * *============================================================================*/ -PRIVATE int get_part_table(dp, device, offset, table) +PRIVATE int get_part_table(dp, device, offset, table, io_ok) struct driver *dp; int device; unsigned long offset; /* sector offset to the table */ struct part_entry *table; /* four entries */ +int *io_ok; { /* Read the partition table for the device, return true iff there were no * errors. @@ -159,6 +160,9 @@ struct part_entry *table; /* four entries */ off_t position; int s; + if(io_ok) + *io_ok = 0; + position = offset << SECTOR_SHIFT; iovec1.iov_addr = (vir_bytes) tmp_buf; iovec1.iov_size = SECTOR_SIZE; @@ -169,6 +173,8 @@ struct part_entry *table; /* four entries */ printf("%s: can't read partition table\n", (*dp->dr_name)()); return 0; } + if(io_ok) + *io_ok = 1; if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) { /* Invalid partition table. */ return 0;