mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
217 lines
5.7 KiB
C
217 lines
5.7 KiB
C
/*=======================================================================*/
|
|
/*+---------------------------------------------------------------------+*/
|
|
/*| |*/
|
|
/*| P-CP/M(tm) Bootstrap Writer for the OLIVETTI M20 (Z8000) |*/
|
|
/*| |*/
|
|
/*| Copyright 1982, Zilog Incorporated. |*/
|
|
/*| |*/
|
|
/*+---------------------------------------------------------------------+*/
|
|
/*=======================================================================*/
|
|
|
|
char copyright[] = "Copyright 1982, Zilog Incorporated";
|
|
|
|
|
|
/* HISTORY
|
|
**
|
|
** 830801 F. Zlotnick (Zilog) -- written
|
|
**
|
|
*/
|
|
|
|
#include "portab.h"
|
|
#include "cpm.h"
|
|
#include "bdos.h"
|
|
#include "stdio.h"
|
|
#include "xout.h"
|
|
|
|
#define CDATA 0 /* Parameter for map_adr() */
|
|
#define DIRSEC 1 /* Parameter for BIOS Write call */
|
|
|
|
#define SETTRK 10 /* BIOS Function 10 = Set Track */
|
|
#define SETSEC 11 /* BIOS Function 11 = Set Sector */
|
|
#define BSETDMA 12 /* BIOS Function 12 = Set DMA Addr */
|
|
#define WSECTOR 14 /* BIOS Function 14 = Write Sector */
|
|
|
|
XADDR physdir; /* Segmented address of dirbuf */
|
|
|
|
struct dpbs idpb; /* Disk Parameter Block */
|
|
struct bios_parm ibp; /* BIOS param block for BDOS call 50*/
|
|
XADDR physibp; /* physical address of ibp structure*/
|
|
|
|
extern long map_adr(); /* Function to return physical addr */
|
|
|
|
#define BPLS 128 /* Bytes per logical sector */
|
|
#define BPS 256 /* Bytes per sector */
|
|
#define BPS0 128 /* Bytes per sector, trk 0 */
|
|
#define SPT 16 /* sectors per track */
|
|
#define LSPT 32 /* Logical sectors per track */
|
|
#define SYSTRKS 2 /* Number of boot tracks */
|
|
#define SYSSIZE SPT*BPS*SYSTRKS /* Max size of bootstrap */
|
|
#define STARTRK 1 /* Track number to start on */
|
|
|
|
FILE *fin;
|
|
|
|
char syscode[SYSSIZE]; /* Hold the entire bootstrap here! */
|
|
char *system = "CPMLDR.SYS"; /* Name of the prog to boot */
|
|
|
|
#ifdef OLIVETTI
|
|
extern char T0S0[]; /* Track 0 Sector 0 */
|
|
extern char T1S0[]; /* Track 1 Sector 0 */
|
|
extern char T1S1[]; /* Track 1 Sector 1 */
|
|
#define HDRSIZE 24 /* # bytes in track 1 sect 1 header */
|
|
#endif
|
|
|
|
struct x_hdr xh;
|
|
struct x_sg xs;
|
|
int dsknum; /* Drive number 0-15 = A-P */
|
|
|
|
main(argc,argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
register int i, j, c;
|
|
register char *p;
|
|
long fsize;
|
|
int curdsk; /* Good to remember, & reset*/
|
|
|
|
if(argc != 3) usage();
|
|
system = *++argv;
|
|
if( (dsknum = **++argv - 'a') < 0 || dsknum > 15) {
|
|
printf("putboot: Illegal drive code %c\n", *argv[0]);
|
|
exit(1);
|
|
}
|
|
curdsk = _ret_cdisk();
|
|
_get_dpb(map_adr((long) &idpb, CDATA)); /* Physaddr of idpb */
|
|
if( (fin = fopenb(system, "r")) == NULL) {
|
|
printf("putboot: Can't open bootstrap file %s\n", system);
|
|
exit(1);
|
|
}
|
|
fsize = 0L;
|
|
|
|
/* read file header */
|
|
|
|
p = (char *) &xh;
|
|
for (i = 0; i < sizeof(xh); i++)
|
|
*p++ = (char) getc(fin);
|
|
|
|
/* read and count segment headers to get file size */
|
|
for (i = 0; i < xh.x_nseg; i++) {
|
|
p = (char *) &xs;
|
|
for( j = 0; j < sizeof(xs); j++)
|
|
*p++ = (char) getc(fin);
|
|
if( xs.x_sg_typ != X_SG_BSS && xs.x_sg_typ != X_SG_STK)
|
|
fsize += xs.x_sg_len;
|
|
}
|
|
if (fsize > SYSSIZE) {
|
|
printf("Bootstrap too big\n");
|
|
exit(1);
|
|
}
|
|
else
|
|
printf("Bootstrap file is %ld bytes\n", fsize);
|
|
p = syscode;
|
|
#ifdef OLIVETTI
|
|
for( i = 0; i < BPS; i++) *p++ = T1S0[i];
|
|
for( i = 0; i < HDRSIZE; i++) *p++ = T1S1[i];
|
|
#endif
|
|
while(fsize--) {
|
|
if( (c = getc(fin)) == EOF) {
|
|
printf("Unexpected EOF in %s, %ld left\n",system,fsize);
|
|
exit(1);
|
|
}
|
|
*p++ = c;
|
|
}
|
|
|
|
/*
|
|
** At this point, the entire bootstrap program code and data has been loaded
|
|
** into the array named "syscode", preceded by a bunch of PCOS garbage
|
|
** which the Olivetti boot PROM expects to find there. Now we use direct
|
|
** BIOS calls to write the syscode array out to the proper area on disk.
|
|
** For the Olivetti, this is tracks 1 and 2, since track 0 is special.
|
|
*/
|
|
|
|
putboot(syscode);
|
|
printf("Bootstrap has been written.\n");
|
|
_sel_disk(curdsk); /* reselect original disk*/
|
|
}
|
|
|
|
putboot(code)
|
|
char *code;
|
|
{
|
|
register int i; /* Handy index */
|
|
register int nlsecs; /* # logical sectors in boot*/
|
|
register char *p; /* ptr to next part of code */
|
|
|
|
int track; /* Current track */
|
|
int sector; /* Current sector */
|
|
|
|
physibp = map_adr( (long) &ibp, CDATA );
|
|
nlsecs = SYSTRKS * LSPT; /* size / log secs per trk */
|
|
|
|
/* Pause for the user to insert disk */
|
|
/* pause(drvname); */
|
|
|
|
#ifdef OLIVETTI
|
|
/* Olivetti Track 0 Sector 0 is special */
|
|
_sel_disk(dsknum); /* select as current disk */
|
|
putblk(0, 0, T0S0);
|
|
#endif
|
|
p = code;
|
|
for(i = 0; i < nlsecs; i++) {
|
|
track = STARTRK + i/LSPT;
|
|
sector = i%LSPT;
|
|
putblk(track, sector, p);
|
|
p += BPLS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Function to select a given track for writing on, on the current disk.
|
|
* Makes use of the BDOS direct BIOS call to issue Bios function 10.
|
|
*/
|
|
settrk(n)
|
|
int n;
|
|
{
|
|
ibp.req = SETTRK; /* BIOS request number 10 */
|
|
ibp.p1 = (long) n; /* parameter = track # */
|
|
_bios_call( physibp ); /* Pass seg ibp address */
|
|
}
|
|
|
|
/*
|
|
* Function to put block i of the boot track.
|
|
*/
|
|
putblk(trk, sec, addr)
|
|
int trk, sec;
|
|
char *addr;
|
|
{
|
|
register int n;
|
|
|
|
_sel_disk(dsknum); /* select as current disk */
|
|
settrk(trk);
|
|
|
|
n = sec + 1; /* sector number */
|
|
ibp.req = SETSEC; /* BIOS request number 11 */
|
|
ibp.p1 = (long) n; /* parameter = sector # */
|
|
_bios_call( physibp ); /* Pass seg ibp address */
|
|
|
|
/* Sector is now set; now set dma address. */
|
|
|
|
ibp.req = BSETDMA; /* BIOS Request number 12 */
|
|
ibp.p1 = map_adr( (long) addr, CDATA);
|
|
/* param = seg address of I/O buffer */
|
|
_bios_call( physibp ); /* Call BIOS */
|
|
|
|
/* Now can do a write */
|
|
|
|
ibp.req = WSECTOR; /* BIOS Request number 14 */
|
|
ibp.p1 = DIRSEC; /* Complete write immediately */
|
|
_bios_call( physibp ); /* Do it! */
|
|
}
|
|
|
|
/*
|
|
* If the user invoked us with the wrong number of args...
|
|
*/
|
|
usage()
|
|
{
|
|
printf("Usage: putboot <filename> <drivecode>\n");
|
|
exit(1);
|
|
}
|