ata-pci support for at driver.

added a hook in libdriver for HARD_INT messages.
This commit is contained in:
Ben Gras 2005-08-25 08:19:11 +00:00
parent a72050e805
commit ae5f1f2286
10 changed files with 271 additions and 81 deletions

View File

@ -8,6 +8,7 @@ s = $i/sys
m = $i/minix
b = $i/ibm
d = ..
p = ../libpci
# programs, flags, etc.
MAKE = exec make
@ -17,15 +18,19 @@ LDFLAGS = -i
LIBS = -lsysutil -lsys -ltimers
OBJ = at_wini.o
LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
LIBPCI = $p/pci.o $p/pci_table.o
# build local binary
all build: $(DRIVER)
$(DRIVER): $(OBJ) $(LIBDRIVER)
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
$(DRIVER): $(OBJ) $(LIBDRIVER) $(LIBPCI)
$(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS) $(LIBPCI)
install -S 8k $(DRIVER)
$(LIBPCI):
cd $p && $(MAKE)
$(LIBDRIVER):
cd $d/libdriver && $(MAKE)

View File

@ -6,6 +6,7 @@
* at_winchester_task: main entry when system is brought up
*
* Changes:
* Aug 19, 2005 ata pci support, supports SATA (Ben Gras)
* Nov 18, 2004 moved AT disk driver to user-space (Jorrit N. Herder)
* Aug 20, 2004 watchdogs replaced by sync alarms (Jorrit N. Herder)
* Mar 23, 2000 added ATAPI CDROM support (Michael Temari)
@ -14,6 +15,8 @@
*/
#include "at_wini.h"
#include "../libpci/pci.h"
#include <minix/sysutil.h>
#include <minix/keymap.h>
#include <sys/ioc_disk.h>
@ -139,7 +142,8 @@ struct command {
#define WAKEUP (32*HZ) /* drive may be out for 31 seconds max */
/* Miscellaneous. */
#define MAX_DRIVES 4 /* this driver supports 4 drives (d0 - d3) */
#define MAX_DRIVES 8
#define COMPAT_DRIVES 4
#if _WORD_SIZE > 2
#define MAX_SECS 256 /* controller can transfer this many sectors */
#else
@ -168,15 +172,25 @@ struct command {
/* Timeouts and max retries. */
int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
int wakeup_ticks = WAKEUP;
long w_standard_timeouts = 0;
long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0;
int w_testing = 0, w_silent = 0;
int w_next_drive = 0;
/* Variables. */
/* wini is indexed by controller first, then drive (0-3).
* controller 0 is always the 'compatability' ide controller, at
* the fixed locations, whether present or not.
*/
PRIVATE struct wini { /* main drive struct, one entry per drive */
unsigned state; /* drive state: deaf, initialized, dead */
unsigned w_status; /* device status register */
unsigned base; /* base register of the register file */
unsigned irq; /* interrupt request line */
unsigned irq_mask; /* 1 << irq */
unsigned irq_need_ack; /* irq needs to be acknowledged */
int irq_hook_id; /* id of irq hook at the kernel */
unsigned lcylinders; /* logical number of cylinders (BIOS) */
unsigned lheads; /* logical number of heads */
@ -193,18 +207,22 @@ PRIVATE struct wini { /* main drive struct, one entry per drive */
} wini[MAX_DRIVES], *w_wn;
PRIVATE int w_device = -1;
PRIVATE int w_controller = -1;
PRIVATE int w_major = -1;
PRIVATE char w_id_string[40];
PRIVATE int win_tasknr; /* my task number */
PRIVATE int w_command; /* current command in execution */
PRIVATE u8_t w_byteval; /* used for SYS_IRQCTL */
PRIVATE int w_status; /* status after interrupt */
PRIVATE int w_drive; /* selected drive */
PRIVATE int w_controller; /* selected controller */
PRIVATE struct device *w_dv; /* device's base and size */
FORWARD _PROTOTYPE( void init_params, (void) );
FORWARD _PROTOTYPE( void init_drive, (struct wini *, int, int, int, int, int));
FORWARD _PROTOTYPE( void init_params_pci, (int) );
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( struct device *w_prepare, (int device) );
FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) );
FORWARD _PROTOTYPE( int w_identify, (void) );
FORWARD _PROTOTYPE( char *w_name, (void) );
FORWARD _PROTOTYPE( int w_specify, (void) );
@ -213,8 +231,10 @@ FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
FORWARD _PROTOTYPE( void w_need_reset, (void) );
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
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 w_hw_int, (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) );
@ -245,7 +265,8 @@ PRIVATE struct driver w_dtab = {
nop_alarm, /* ignore leftover alarms */
nop_cancel, /* ignore CANCELs */
nop_select, /* ignore selects */
w_other /* catch-all for unrecognized commands and ioctls */
w_other, /* catch-all for unrecognized commands and ioctls */
w_hw_int /* leftover hardware interrupts */
};
/*===========================================================================*
@ -270,43 +291,153 @@ PRIVATE void init_params()
int drive, nr_drives;
struct wini *wn;
u8_t params[16];
int s;
int s, i;
/* Get the number of drives from the BIOS data area */
if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR,
SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
panic(w_name(), "Couldn't read BIOS", s);
if ((nr_drives = params[0]) > 2) nr_drives = 2;
/* Boot variables. */
env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1);
env_parse("ata_instance", "d", 0, &w_instance, 0, 8);
for (drive = 0, wn = wini; drive < MAX_DRIVES; drive++, wn++) {
if (drive < nr_drives) {
/* Copy the BIOS parameter vector */
vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
SELF, D, (vir_bytes) parv, size)) != OK)
panic(w_name(), "Couldn't read BIOS", s);
if(w_instance == 0) {
/* Get the number of drives from the BIOS data area */
if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR,
SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
panic(w_name(), "Couldn't read BIOS", s);
if ((nr_drives = params[0]) > 2) nr_drives = 2;
/* Calculate the address of the parameters and copy them */
if ((s=sys_vircopy(
SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0],
SELF, D, (phys_bytes) params, 16L))!=OK)
panic(w_name(),"Couldn't copy parameters", s);
for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) {
if (drive < nr_drives) {
/* Copy the BIOS parameter vector */
vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
SELF, D, (vir_bytes) parv, size)) != OK)
panic(w_name(), "Couldn't read BIOS", s);
/* Calculate the address of the parameters and copy them */
if ((s=sys_vircopy(
SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0],
SELF, D, (phys_bytes) params, 16L))!=OK)
panic(w_name(),"Couldn't copy parameters", s);
/* Copy the parameters to the structures of the drive */
wn->lcylinders = bp_cylinders(params);
wn->lheads = bp_heads(params);
wn->lsectors = bp_sectors(params);
wn->precomp = bp_precomp(params) >> 2;
}
/* Copy the parameters to the structures of the drive */
wn->lcylinders = bp_cylinders(params);
wn->lheads = bp_heads(params);
wn->lsectors = bp_sectors(params);
wn->precomp = bp_precomp(params) >> 2;
}
wn->ldhpref = ldh_init(drive);
wn->max_count = MAX_SECS << SECTOR_SHIFT;
/* Base I/O register to address controller. */
wn->base = drive < 2 ? REG_BASE0 : REG_BASE1;
/* Fill in non-BIOS parameters. */
init_drive(wn, drive < 2 ? REG_BASE0 : REG_BASE1, NO_IRQ, 0, 0, drive);
w_next_drive++;
}
}
env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1);
/* Look for controllers on the pci bus. Skip none the first instance,
* skip one and then 2 for every instance, for every next instance.
*/
if(w_instance == 0)
init_params_pci(0);
else
init_params_pci(w_instance*2-1);
}
#define ATA_IF_NOTCOMPAT1 (1L << 0)
#define ATA_IF_NOTCOMPAT2 (1L << 2)
/*============================================================================*
* init_drive *
*============================================================================*/
PRIVATE void init_drive(struct wini *w, int base, int irq, int ack, int hook, int drive)
{
w->state = 0;
w->w_status = 0;
w->base = base;
w->irq = irq;
w->irq_mask = 1 << irq;
w->irq_need_ack = ack;
w->irq_hook_id = hook;
w->ldhpref = ldh_init(drive);
w->max_count = MAX_SECS << SECTOR_SHIFT;
}
/*============================================================================*
* init_params_pci *
*============================================================================*/
PRIVATE void init_params_pci(int skip)
{
int r, devind, drive;
u16_t vid, did;
pci_init();
for(drive = w_next_drive; drive < MAX_DRIVES; drive++)
wini[drive].state = IGNORING;
for(r = pci_first_dev(&devind, &vid, &did);
r != 0 && w_next_drive < MAX_DRIVES; r = pci_next_dev(&devind, &vid, &did)) {
int interface, irq, irq_hook, any_foud = 0;
/* Base class must be 01h (mass storage), subclass must
* be 01h (ATA).
*/
if(pci_attr_r8(devind, PCI_BCR) != 0x01 ||
pci_attr_r8(devind, PCI_SCR) != 0x01) {
continue;
}
/* Found a controller.
* Programming interface register tells us more.
*/
interface = pci_attr_r8(devind, PCI_PIFR);
irq = pci_attr_r8(devind, PCI_ILR);
/* Any non-compat drives? */
if(interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2)) {
int s;
irq_hook = irq;
if(skip > 0) {
if(w_pci_debug) printf("atapci skipping controller (remain %d)\n", skip);
skip--;
continue;
}
if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) {
printf("atapci: couldn't set IRQ policy %d\n", irq);
continue;
}
if ((s=sys_irqenable(&irq_hook)) != OK) {
printf("atapci: couldn't enable IRQ line %d\n", irq);
continue;
}
} else {
/* If not.. this is not the ata-pci controller we're
* looking for.
*/
if(w_pci_debug) printf("atapci skipping compatability controller\n");
continue;
}
/* Primary channel not in compatability mode? */
if(interface & ATA_IF_NOTCOMPAT1) {
u32_t base;
base = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
if(base != REG_BASE0 && base != REG_BASE1) {
init_drive(&wini[w_next_drive], base, irq, 1, irq_hook, 0);
init_drive(&wini[w_next_drive+1], base, irq, 1, irq_hook, 1);
if(w_pci_debug)
printf("atapci %d: 0x%x irq %d\n", devind, base, irq);
} else printf("atapci: ignored drives on primary channel, base %x\n", base);
}
/* Secondary channel not in compatability mode? */
if(interface & ATA_IF_NOTCOMPAT2) {
u32_t base;
base = pci_attr_r32(devind, PCI_BAR_3) & 0xffffffe0;
if(base != REG_BASE0 && base != REG_BASE1) {
init_drive(&wini[w_next_drive+2], base, irq, 1, irq_hook, 2);
init_drive(&wini[w_next_drive+3], base, irq, 1, irq_hook, 3);
if(w_pci_debug)
printf("atapci %d: 0x%x irq %d\n", devind, base, irq);
} else printf("atapci: ignored drives on secondary channel, base %x\n", base);
}
w_next_drive += 4;
}
}
/*============================================================================*
@ -389,11 +520,9 @@ message *m_ptr;
/*===========================================================================*
* w_prepare *
*===========================================================================*/
PRIVATE struct device *w_prepare(device)
int device;
PRIVATE struct device *w_prepare(int device)
{
/* Prepare for I/O on a device. */
w_device = device;
if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */
w_drive = device / DEV_PER_DRIVE; /* save drive number */
@ -505,7 +634,7 @@ PRIVATE int w_identify()
}
#if VERBOSE
printf("%s: user-space AT Winchester driver detected ", w_name());
printf("%s: user-space AT driver detected ", w_name());
if (wn->state & (SMART|ATAPI)) {
printf("%.40s\n", id_string);
} else {
@ -513,13 +642,15 @@ PRIVATE int w_identify()
}
#endif
/* Everything looks OK; register IRQ so we can stop polling. */
wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
wn->irq_hook_id = wn->irq; /* id to be returned if interrupt occurs */
if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK)
panic(w_name(), "coudn't set IRQ policy", s);
if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
panic(w_name(), "coudn't enable IRQ line", s);
if(wn->irq == NO_IRQ) {
/* Everything looks OK; register IRQ so we can stop polling. */
wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
wn->irq_hook_id = wn->irq; /* id to be returned if interrupt occurs */
if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK)
panic(w_name(), "couldn't set IRQ policy", s);
if ((s=sys_irqenable(&wn->irq_hook_id)) != OK)
panic(w_name(), "couldn't enable IRQ line", s);
}
wn->state |= IDENTIFIED;
return(OK);
}
@ -714,7 +845,7 @@ unsigned nr_req; /* length of request vector */
/* First an interrupt, then data. */
if ((r = at_intr_wait()) != OK) {
/* An error, send data to the bit bucket. */
if (w_status & STATUS_DRQ) {
if (w_wn->w_status & STATUS_DRQ) {
if ((s=sys_insw(wn->base + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK)
panic(w_name(),"Call to sys_insw() failed", s);
}
@ -795,7 +926,7 @@ struct command *cmd; /* Command block */
*/
sys_setalarm(wakeup_ticks, 0);
w_status = STATUS_ADMBSY;
wn->w_status = STATUS_ADMBSY;
w_command = cmd->command;
pv_set(outbyte[0], base + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0);
pv_set(outbyte[1], base + REG_PRECOMP, cmd->precomp);
@ -816,10 +947,13 @@ PRIVATE void w_need_reset()
{
/* The controller needs to be reset. */
struct wini *wn;
int dr = 0;
for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
wn->state |= DEAF;
wn->state &= ~INITIALIZED;
for (wn = wini; wn < &wini[MAX_DRIVES]; wn++, dr++) {
if (wn->base == w_wn->base) {
wn->state |= DEAF;
wn->state &= ~INITIALIZED;
}
}
}
@ -831,8 +965,8 @@ struct driver *dp;
message *m_ptr;
{
/* Device close: Release a device. */
if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
if (w_prepare(m_ptr->DEVICE) == NIL_DEV)
return(ENXIO);
w_wn->open_ct--;
#if ENABLE_ATAPI
if (w_wn->open_ct == 0 && (w_wn->state & ATAPI)) atapi_close();
@ -882,7 +1016,7 @@ PRIVATE void w_timeout(void)
if(w_testing) wn->state |= IGNORING; /* Kick out this drive. */
else if(!w_silent) printf("%s: timeout on command %02x\n", w_name(), w_command);
w_need_reset();
w_status = 0;
wn->w_status = 0;
}
}
@ -920,8 +1054,16 @@ PRIVATE int w_reset()
/* The error register should be checked now, but some drives mess it up. */
for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) {
if (wn->base == w_wn->base) wn->state &= ~DEAF;
if (wn->base == w_wn->base) {
wn->state &= ~DEAF;
if (w_wn->irq_need_ack) {
/* Make sure irq is actually enabled.. */
sys_irqenable(&w_wn->irq_hook_id);
}
}
}
return(OK);
}
@ -936,14 +1078,14 @@ PRIVATE void w_intr_wait()
if (w_wn->irq != NO_IRQ) {
/* Wait for an interrupt that sets w_status to "not busy". */
while (w_status & (STATUS_ADMBSY|STATUS_BSY)) {
while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
receive(ANY, &m); /* expect HARD_INT message */
if (m.m_type == SYN_ALARM) { /* but check for timeout */
w_timeout(); /* a.o. set w_status */
} else if (m.m_type == HARD_INT) {
sys_inb((w_wn->base + REG_STATUS), &w_status);
}
else {
sys_inb(w_wn->base + REG_STATUS, &w_wn->w_status);
ack_irqs(m.NOTIFY_ARG);
} else {
printf("AT_WINI got unexpected message %d from %d\n",
m.m_type, m.m_source);
}
@ -964,18 +1106,18 @@ PRIVATE int at_intr_wait()
int s,inbval; /* read value with sys_inb */
w_intr_wait();
if ((w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) {
r = OK;
} else {
if ((s=sys_inb(w_wn->base + REG_ERROR, &inbval)) != OK)
panic(w_name(),"Couldn't read register",s);
if ((w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) {
r = ERR_BAD_SECTOR; /* sector marked bad, retries won't help */
} else {
r = ERR; /* any other error */
}
}
w_status |= STATUS_ADMBSY; /* assume still busy with I/O */
w_wn->w_status |= STATUS_ADMBSY; /* assume still busy with I/O */
return(r);
}
@ -995,9 +1137,9 @@ int value; /* required status */
int s;
getuptime(&t0);
do {
if ((s=sys_inb(w_wn->base + REG_STATUS, &w_status)) != OK)
if ((s=sys_inb(w_wn->base + REG_STATUS, &w_wn->w_status)) != OK)
panic(w_name(),"Couldn't read register",s);
if ((w_status & mask) == value) {
if ((w_wn->w_status & mask) == value) {
return 1;
}
} while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks );
@ -1229,7 +1371,7 @@ unsigned cnt;
printf("%s: timeout (BSY|DRQ -> DRQ)\n");
return(ERR);
}
w_status |= STATUS_ADMBSY; /* Command not at all done yet. */
wn->w_status |= STATUS_ADMBSY; /* Command not at all done yet. */
/* Send the command packet to the device. */
if ((s=sys_outsw(wn->base + REG_DATA, SELF, packet, 12)) != OK)
@ -1246,8 +1388,9 @@ message *m;
{
int r, timeout, prev;
if(m->m_type != DEV_IOCTL || m->REQUEST != DIOCTIMEOUT)
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)
@ -1284,6 +1427,39 @@ message *m;
return OK;
}
/*============================================================================*
* w_hw_int *
*============================================================================*/
PRIVATE int w_hw_int(dr, m)
struct driver *dr;
message *m;
{
/* Leftover interrupt(s) received; ack it/them. */
ack_irqs(m->NOTIFY_ARG);
return OK;
}
/*============================================================================*
* ack_irqs *
*============================================================================*/
PRIVATE void ack_irqs(unsigned int irqs)
{
unsigned int drive;
for (drive = 0; drive < MAX_DRIVES && irqs; drive++) {
if(!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack &&
(wini[drive].irq_mask & irqs)) {
if(sys_inb((wini[drive].base + REG_STATUS), &wini[drive].w_status) != OK)
printf("couldn't ack irq on drive %d\n", drive);
if (sys_irqenable(&wini[drive].irq_hook_id) != OK)
printf("couldn't re-enable drive %d\n", drive);
irqs &= ~wini[drive].irq_mask;
}
}
}
/*============================================================================*
* atapi_intr_wait *
*============================================================================*/
@ -1316,11 +1492,11 @@ PRIVATE int atapi_intr_wait()
irr = inbyte[3].value;
if (ATAPI_DEBUG) {
printf("S=%02x E=%02x L=%04x I=%02x\n", w_status, e, len, irr);
printf("S=%02x E=%02x L=%04x I=%02x\n", wn->w_status, e, len, irr);
}
if (w_status & (STATUS_BSY | STATUS_CHECK)) return ERR;
if (wn->w_status & (STATUS_BSY | STATUS_CHECK)) return ERR;
phase = (w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
phase = (wn->w_status & STATUS_DRQ) | (irr & (IRR_COD | IRR_IO));
switch (phase) {
case IRR_COD | IRR_IO:
@ -1351,11 +1527,11 @@ PRIVATE int atapi_intr_wait()
#if 0
/* retry if the media changed */
XXX while (phase == (IRR_IO | IRR_COD) && (w_status & STATUS_CHECK)
XXX while (phase == (IRR_IO | IRR_COD) && (wn->w_status & STATUS_CHECK)
&& (e & ERROR_SENSE) == SENSE_UATTN && --try > 0);
#endif
w_status |= STATUS_ADMBSY; /* Assume not done yet. */
wn->w_status |= STATUS_ADMBSY; /* Assume not done yet. */
return(r);
}
#endif /* ENABLE_ATAPI */

View File

@ -87,7 +87,8 @@ PRIVATE struct driver w_dtab = {
nop_alarm, /* ignore leftover alarms */
nop_cancel, /* ignore CANCELs */
nop_select, /* ignore selects */
nop_other /* catch-all for unrecognized commands and ioctls */
nop_other, /* catch-all for unrecognized commands and ioctls */
NULL /* leftover hardware interrupts */
};
/*===========================================================================*

View File

@ -277,6 +277,7 @@ PRIVATE struct driver f_dtab = {
f_expire_tmrs,/* expire all alarm timers */
nop_cancel,
nop_select,
NULL,
NULL
};

View File

@ -77,7 +77,7 @@ struct driver *dp; /* Device dependent entry points. */
int r, proc_nr;
message mess;
int s;
int s, p;
/* Get a DMA buffer. */
init_buffer();
@ -88,7 +88,7 @@ struct driver *dp; /* Device dependent entry points. */
while (TRUE) {
/* Wait for a request to read or write a disk block. */
receive(ANY, &mess);
if(receive(ANY, &mess) != OK) continue;
device_caller = mess.m_source;
proc_nr = mess.PROC_NR;
@ -107,6 +107,9 @@ struct driver *dp; /* Device dependent entry points. */
case DEV_SCATTER: r = do_vrdwt(dp, &mess); break;
case HARD_INT: /* leftover interrupt or expired timer. */
if(dp->dr_hw_int) {
(*dp->dr_hw_int)(dp, &mess);
}
continue;
case SYS_SIG: (*dp->dr_signal)(dp, &mess);
continue; /* don't reply */

View File

@ -42,6 +42,7 @@ struct driver {
_PROTOTYPE( int (*dr_cancel), (struct driver *dp, message *m_ptr) );
_PROTOTYPE( int (*dr_select), (struct driver *dp, message *m_ptr) );
_PROTOTYPE( int (*dr_other), (struct driver *dp, message *m_ptr) );
_PROTOTYPE( int (*dr_hw_int), (struct driver *dp, message *m_ptr) );
};
#if (CHIP == INTEL)

View File

@ -50,7 +50,8 @@ PRIVATE struct driver log_dtab = {
nop_alarm, /* no alarm */
log_cancel, /* CANCEL request */
log_select, /* DEV_SELECT request */
log_other /* Unrecognized messages */
log_other, /* Unrecognized messages */
NULL /* HW int */
};
extern int device_caller;

View File

@ -56,6 +56,7 @@ PRIVATE struct driver m_dtab = {
nop_alarm,
nop_cancel,
nop_select,
NULL,
NULL
};

View File

@ -48,6 +48,7 @@ PRIVATE struct driver r_dtab = {
r_random, /* get randomness from kernel (alarm) */
nop_cancel,
nop_select,
NULL,
NULL
};

View File

@ -283,8 +283,8 @@ PUBLIC void main(void)
case DEV_SELECT: do_select(tp, &tty_mess); break;
case CANCEL: do_cancel(tp, &tty_mess); break;
default:
printf("Warning, TTY got unexpected request %d from %d\n",
tty_mess.m_type, tty_mess.m_source);
printf("Warning, TTY got unexpected request %d from %d (open is %d)\n",
tty_mess.m_type, tty_mess.m_source, DEV_OPEN);
tty_reply(TASK_REPLY, tty_mess.m_source,
tty_mess.PROC_NR, EINVAL);
}