diff --git a/drivers/floppy/Makefile b/drivers/floppy/Makefile index 55f0fdcc5..b9e59b974 100644 --- a/drivers/floppy/Makefile +++ b/drivers/floppy/Makefile @@ -29,8 +29,8 @@ $(LIBDRIVER): cd $d/libdriver && $(MAKE) # install with other drivers -install: /usr/sbin/$(DRIVER) -/usr/sbin/$(DRIVER): $(DRIVER) +install: /sbin/$(DRIVER) +/sbin/$(DRIVER): $(DRIVER) install -o root -cs $? $@ # clean up local files diff --git a/drivers/floppy/floppy.c b/drivers/floppy/floppy.c index 0d775d8a6..6745258f7 100644 --- a/drivers/floppy/floppy.c +++ b/drivers/floppy/floppy.c @@ -33,12 +33,14 @@ #define FDC_DATA 0x3F5 /* floppy disk controller data register */ #define FDC_RATE 0x3F7 /* transfer rate register */ #define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */ -#define DMA_TOP 0x081 /* port for top 4 bits of 20-bit DMA addr */ +#define DMA_TOP 0x081 /* port for top 8 bits of 24-bit DMA addr */ #define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */ #define DMA_FLIPFLOP 0x00C /* DMA byte pointer flip-flop */ #define DMA_MODE 0x00B /* DMA mode port */ #define DMA_INIT 0x00A /* DMA init port */ -#define DMA_RESET_VAL 0x06 +#define DMA_RESET_VAL 0x006 + +#define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */ /* Status registers returned as result of operation. */ #define ST0 0x00 /* status register 0 */ @@ -245,7 +247,7 @@ FORWARD _PROTOTYPE( char *f_name, (void) ); FORWARD _PROTOTYPE( void f_cleanup, (void) ); FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position, iovec_t *iov, unsigned nr_req) ); -FORWARD _PROTOTYPE( void dma_setup, (int opcode) ); +FORWARD _PROTOTYPE( int dma_setup, (int opcode) ); FORWARD _PROTOTYPE( void start_motor, (void) ); FORWARD _PROTOTYPE( int seek, (void) ); FORWARD _PROTOTYPE( int fdc_transfer, (int opcode) ); @@ -571,7 +573,13 @@ unsigned nr_req; /* length of request vector */ /* Set up the DMA chip and perform the transfer. */ if (r == OK) { - dma_setup(opcode); + if (dma_setup(opcode) != OK) { + /* This can only fail for addresses above 16MB + * that cannot be handled by the controller, + * because it uses 24-bit addressing. + */ + return(EIO); + } r = fdc_transfer(opcode); } @@ -627,7 +635,7 @@ unsigned nr_req; /* length of request vector */ /*===========================================================================* * dma_setup * *===========================================================================*/ -PRIVATE void dma_setup(opcode) +PRIVATE int dma_setup(opcode) int opcode; /* DEV_GATHER or DEV_SCATTER */ { /* The IBM PC can perform DMA operations by using the DMA chip. To use it, @@ -636,10 +644,21 @@ int opcode; /* DEV_GATHER or DEV_SCATTER */ * opcode. This routine sets up the DMA chip. Note that the chip is not * capable of doing a DMA across a 64K boundary (e.g., you can't read a * 512-byte block starting at physical address 65520). + * + * Warning! Also note that it's not possible to do DMA above 16 MB because + * the ISA bus uses 24-bit addresses. Addresses above 16 MB therefore will + * be interpreted modulo 16 MB, dangerously overwriting arbitrary memory. + * A check here denies the I/O if the address is out of range. */ pvb_pair_t byte_out[9]; int s; + /* First check the DMA memory address not to exceed maximum. */ + if (tmp_phys != (tmp_phys & DMA_ADDR_MASK)) { + report("FLOPPY", "DMA denied because address out of range", NO_NUM); + return(EIO); + } + /* Set up the DMA registers. (The comment on the reset is a bit strong, * it probably only resets the floppy channel.) */ @@ -655,6 +674,7 @@ int opcode; /* DEV_GATHER or DEV_SCATTER */ if ((s=sys_voutb(byte_out, 9)) != OK) panic("FLOPPY","Sys_voutb in dma_setup() failed", s); + return(OK); } diff --git a/drivers/libdriver/driver.c b/drivers/libdriver/driver.c index a95f7014b..bc6e776d7 100644 --- a/drivers/libdriver/driver.c +++ b/drivers/libdriver/driver.c @@ -41,6 +41,7 @@ #if (CHIP == INTEL) + #if USE_EXTRA_DMA_BUF && DMA_BUF_SIZE < 2048 /* A bit extra scratch for the Adaptec driver. */ #define BUF_EXTRA (2048 - DMA_BUF_SIZE) @@ -156,7 +157,7 @@ PRIVATE void init_buffer() tmp_buf += left; tmp_phys += left; } -#endif /* CHIP != INTEL */ +#endif /* CHIP == INTEL */ } diff --git a/etc/rc b/etc/rc index 4fa646b3a..96debe7c6 100755 --- a/etc/rc +++ b/etc/rc @@ -51,8 +51,10 @@ start) # National keyboard? test -f /etc/keymap && loadkeys /etc/keymap - # Start crucial system services + # Start crucial system services. The floppy driver *must* be loaded + # first, as it needs memory below 16MB in order to do ISA DMA. echo -n "Starting services:" + up floppy "" /dev/fd0 up is "" up cmos "" /dev/cmos echo . diff --git a/etc/usr/rc b/etc/usr/rc index 13ab0bc9c..40f57f44d 100644 --- a/etc/usr/rc +++ b/etc/usr/rc @@ -102,7 +102,6 @@ start) done up inet "" up printer "" /dev/lp -# up floppy "" /dev/fd0 echo . # Network initialization.