From a0f44650456531918c0132df2e3cdb92521ad150 Mon Sep 17 00:00:00 2001 From: Bart Oldeman Date: Thu, 30 Oct 2003 12:22:06 +0000 Subject: [PATCH] From Eric Luttmann: fix for multi-segment device drivers; preserve rq_endaddr between init calls for the same driver. git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@722 6ac86273-5f31-0410-b378-82cca8765d1b --- kernel/config.c | 9 ++++++++- kernel/init-mod.h | 2 +- kernel/main.c | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/kernel/config.c b/kernel/config.c index 544f36d..00b84a9 100644 --- a/kernel/config.c +++ b/kernel/config.c @@ -1384,8 +1384,15 @@ STATIC BOOL LoadDevice(BYTE * pLine, char FAR *top, COUNT mode) dhp = MK_FP(base, 0); + /* NOTE - Modification for multisegmented device drivers: */ + /* In order to emulate the functionallity experienced with other */ + /* DOS operating systems, the original 'top' end address is */ + /* updated with the end address returned from the INIT request. */ + /* The updated end address is then used when issuing the next */ + /* INIT request for the following device driver within the file */ + for (next_dhp = NULL; FP_OFF(next_dhp) != 0xffff && - (result = init_device(dhp, szBuf, mode, top)) == SUCCESS; + (result = init_device(dhp, szBuf, mode, &top)) == SUCCESS; dhp = next_dhp) { next_dhp = MK_FP(FP_SEG(dhp), FP_OFF(dhp->dh_next)); diff --git a/kernel/init-mod.h b/kernel/init-mod.h index d5452a3..51c6af9 100644 --- a/kernel/init-mod.h +++ b/kernel/init-mod.h @@ -188,7 +188,7 @@ VOID ASMCFUNC FAR cpm_entry(void); /* main.c */ VOID ASMCFUNC FreeDOSmain(void); BOOL init_device(struct dhdr FAR * dhp, char * cmdLine, - COUNT mode, char FAR *top); + COUNT mode, char FAR **top); VOID init_fatal(BYTE * err_msg); /* prf.c */ diff --git a/kernel/main.c b/kernel/main.c index c2c2e49..f71d97a 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -230,7 +230,7 @@ STATIC void init_kernel(void) /* we can read config.sys later. */ LoL->lastdrive = Config.cfgLastdrive; - /* init_device((struct dhdr FAR *)&blk_dev, NULL, 0, ram_top); */ + /* init_device((struct dhdr FAR *)&blk_dev, NULL, 0, &ram_top); */ blk_dev.dh_name[0] = dsk_init(); PreConfig(); @@ -485,7 +485,7 @@ STATIC VOID update_dcb(struct dhdr FAR * dhp) /* If cmdLine is NULL, this is an internal driver */ BOOL init_device(struct dhdr FAR * dhp, char *cmdLine, COUNT mode, - char FAR *r_top) + char FAR **r_top) { request rq; char name[8]; @@ -517,7 +517,7 @@ BOOL init_device(struct dhdr FAR * dhp, char *cmdLine, COUNT mode, rq.r_status = 0; rq.r_command = C_INIT; rq.r_length = sizeof(request); - rq.r_endaddr = r_top; + rq.r_endaddr = *r_top; rq.r_bpbptr = (void FAR *)(cmdLine ? cmdLine : "\n"); rq.r_firstunit = LoL->nblkdev; @@ -546,6 +546,15 @@ BOOL init_device(struct dhdr FAR * dhp, char *cmdLine, COUNT mode, KernelAllocPara(FP_SEG(rq.r_endaddr) + (FP_OFF(rq.r_endaddr) + 15)/16 - FP_SEG(dhp), 'D', name, mode); } + + /* Another fix for multisegmented device drivers: */ + /* To help emulate the functionallity experienced with other DOS */ + /* operating systems when calling multiple device drivers in a */ + /* single driver file, save the end address returned from the */ + /* last INIT call which will then be passed as the end address */ + /* for the next INIT call. */ + + *r_top = (char FAR *)rq.r_endaddr; } if (!(dhp->dh_attr & ATTR_CHAR) && (rq.r_nunits != 0)) @@ -569,7 +578,7 @@ STATIC void InitIO(void) /* Initialize driver chain */ setvec(0x29, int29_handler); /* Requires Fast Con Driver */ do { - init_device(device, NULL, 0, lpTop); + init_device(device, NULL, 0, &lpTop); device = device->dh_next; } while (FP_OFF(device) != 0xffff);