#include "at_wini.h"
#include <minix/utils.h>
#include <minix/keymap.h>
+#include <sys/ioc_disk.h>
#if ENABLE_AT_WINI
/* 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
#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 */
#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 */
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) );
nop_fkey,
nop_cancel,
nop_select,
- NULL
+ w_other /* catch-all for unrecognized commands and ioctls */
};
/* 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);
}
* 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;
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 */
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);
}
* 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. */
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 *
*============================================================================*/
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) );
* 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;
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. */
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
/*============================================================================*
* 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.
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;
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;