hcj@lzaz.ATT.COM (HC Johnson) (11/09/88)
--------------------------------------------------------- The enclosed file, driver.diff allows installing a driver in Minix. This allows reading the clock in the BMS-100 hard disk controller. It turns out that the 13 bytes read are identical to those read on a MEGA. They must use the same chip. Interfacing the SUPRA clock is likely just as simple. -------------------------------cut here------------------ echo x - driver.diff gres '^X' '' > driver.diff << '/' Xkernel/Makefile X9a10 X> bmsclock.o \ X====================================================================== Xkernel/table.c X36,39c36,40 X< winchester_task(), tty_task(), printer_task(); X< X< /* The startup routine of each task is given below, from -NR_TASKS upwards. X< * The order of the names here MUST agree with the numerical values assigned to X--- X> winchester_task(), tty_task(), printer_task(), bmsclock_task(); X> X> /* The startup routine of each task is given below, from -NR_TASKS upwards. X> * The order of the X> names here MUST agree with the numerical values assigned to X42a44 X> bmsclock_task, X====================================================================== Xkernel/stdmp.c X124c124 X< char *nayme[]= {"PRINTR", "TTY ", "WINCHE", "FLOPPY", "RAMDSK", "CLOCK ", X--- X> char *nayme[]= {"BMSCLK", "PRINTR", "TTY ", "WINCHE", "FLOPPY", "RAMDSK", "CLOCK ", X====================================================================== Xfs/table Xh/com.h X54a55,60 X> #define BMSCLOCK -9 /* clock on BMS 100 */ X> # define BMS_READ 3 X> # define BMS_WRITE 4 X> X> #define SERIAL -10 /* serial port */ X> X====================================================================== Xh/const.h X25,26c25,26 X< #define NR_TASKS 8 /* number of tasks in the transfer vector */ X< #define NR_PROCS 16 /* number of slots in proc table */ X--- X> #define NR_TASKS 9 /* number of tasks in the transfer vector */ X> #define NR_PROCS 17 /* number of slots in proc table */ X127,130c127,134 X< no_call, rw_dev, no_call, PRINTER /* 6 = /dev/lp */ X< }; X< X< int max_major = sizeof(dmap)/sizeof(struct dmap); X--- X> no_call, rw_dev, no_call, PRINTER, /* 6 = /dev/lp */ X> no_call, rw_dev, no_call, BMSCLOCK, /* 7 = /dev/bms */ X> #ifdef NOTYET X> no_call, rw_dev, no_call, SERIAL, /* 8 = /dev/ser */ X> #endif X> }; X> X> int max_major = sizeof(dmap)/sizeof(struct dmap); X====================================================================== Xkernel/bmsclock.c X#ifdef ATARI_ST X/* X * This file contains a bms-100 clock driver X * on the Atari ST. X * X * The driver supports two operations: read a bytes and write a bytes. X * It accepts two messages, one for reading and one for writing, X * both using message format m2 and with the same parameters: X * X * m_type DEVICE PROC_NR COUNT POSITION ADRRESS X * ---------------------------------------------------------------- X * | BMS_READ | device | proc nr | bytes | offset | buf ptr | X * |------------+---------+---------+---------+---------+---------| X * | BMS_WRITE | device | proc nr | bytes | offset | buf ptr | X * ---------------------------------------------------------------- X * X * The file contains one entry point: X * X * bmsclock_task: main entry when system is brought up X * X * X */ X X#include "../h/const.h" X#include "../h/type.h" X#include "../h/callnr.h" X#include "../h/com.h" X#include "../h/error.h" X#include "const.h" X#include "type.h" X#include "proc.h" X X#include "staddr.h" X#include "stmfp.h" X#include "stdma.h" X#define MAX_ERRORS 3 X X#define TRACE(x) /* x */ X#define DEBUG(x) x X X/* dis/enable interrupts */ X#define IENABLE() MFP->mf_ierb |= IB_DINT X#define IDISABLE() MFP->mf_ierb &= ~IB_DINT X X/* timing constants */ X XPRIVATE message mess; /* message buffer for in and out */ X X X/*===========================================================================* X * bmsclock_task * X *===========================================================================*/ XPUBLIC bmsclock_task() X{ X register r, drive, minor, caller, procno; X X X /* X * The main loop of the bms clock task. X * It waits for a message, carries it out, and sends a reply. X */ X while (TRUE) { X receive(ANY, &mess); X if (mess.m_source < 0) X panic("bms clock task got message from ", mess.m_source); X TRACE(printf("bms: received %d from %d\n",mess.m_type,mess.m_source)); X caller = mess.m_source; X procno = mess.PROC_NR; X X /* Now carry out the work. */ X switch (mess.m_type) { X case BMS_READ: X case BMS_WRITE: r = do_bms(&mess); break; X default: r = EINVAL; break; X } X X /* Finally, prepare and send the reply message. */ X mess.m_type = TASK_REPLY; X mess.REP_PROC_NR = procno; X mess.REP_STATUS = r; /* # of bytes transferred or error code */ X send(caller, &mess); /* send reply to caller */ X } X} X X X X/*===========================================================================* X * do_bms * X *===========================================================================*/ XPRIVATE int do_bms(mp) Xregister message *mp; X{ X register struct proc *rp; X register r, errors, count, rw, drive, minor; X register long secnum; X register phys_bytes address; X extern phys_bytes umap(); X X rw = mp->m_type; X X minor = mp->DEVICE; X count = mp->COUNT; X if (count <= 0) X return(EOF); X rp = proc_addr(mp->PROC_NR); X address = umap(rp, D, (vir_bytes) mp->ADDRESS, (vir_bytes) count); X if (address == 0) X return(EINVAL); X TRACE(printf("hd%d: %s: sec=%D; cnt=%d\n", X minor, rw == DISK_READ ? "read" : "write", secnum, count)); X rp->p_physio = 1; /* disable (un)shadowing */ X /* This loop allows a failed operation to be repeated. */ X for (errors = 0; errors < MAX_ERRORS; errors++) { X r = do_xbms(address, count, rw); X if (r == OK) X break; /* if successful, exit loop */ X } X rp->p_physio = 0; /* enable (un)shadowing */ X if (r != OK) X return(EIO); X return(count ); X} X X/*===========================================================================* X * do_xbms * X *===========================================================================*/ X XPRIVATE int do_xbms(address, count, rw) Xphys_bytes address; Xint count; Xint rw; X{ X X register r, s, wrbit; X register index; X register char *cp; X char lbuf[13]; X extern void dmaint(); X X X /* X * Carry out the transfer. All parameters have been checked and X * are set up properly. X * X * Every single byte written to the hdc will cause an interrupt. X * Thus disable interrupts while communicating with hdc. Ready test X * will be done by busy waiting. Only for real hard disk operations X * interrupts will be enabled. X */ X TRACE(printf("hd address:0x%X count=%d cmd:%s\n", X address, count, (rw==0)?"READ":"WRITE") X ); X IDISABLE(); X X dmagrab(BMSCLOCK, dmaint); X if (rw == DISK_READ) { X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe1; X for(r=100;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe5; X for(index = 0; index<13; index++) { X DMA->dma_mode = FDC | HDC | A0; X DMA->dma_data = (index << 4); X for(r=3;r>0;r--) ; /* pause */ X lbuf[index] = DMA->dma_data & 0xf; X } X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe0; X DMA->dma_mode = FDC ; X X for(index=0,cp=(char*)address; index<count; index++) X *cp++ = lbuf[index]; X/* reaccess */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe1; X for(r=100;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe5; X for(index = 7; index<12; index++) { X DMA->dma_mode = FDC | HDC | A0; X DMA->dma_data = (index << 4); X for(r=3;r>0;r--) ; /* pause */ X lbuf[index] = DMA->dma_data & 0xf; X } X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe1; X X s = (lbuf[10] * 10 + lbuf[9]) ; X r = s + lbuf[12] * 10 + lbuf[11]; X if (s > 2) X lbuf[8] &= 3; X if(r != 20) { X if ((r &= 3) == 0) X lbuf[8] |= 4; X } X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe9; X for(r=100;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC | A0; X index = 8; X r = (lbuf[index] & 0xf) + (index<<4); X DMA->dma_data = r; X for(r=1;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xeb; X for(r=1;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe9; X for(r=1;r>0;r--) ; /* pause */ X DMA->dma_mode = FDC | HDC; X DMA->dma_data = 0xe0; X DMA->dma_mode = FDC ; X X } else if (rw = DISK_WRITE) { X/* reserve for setting clock */ X return(EINVAL); X } else { X/* reserve for screen blanker */ X return(EINVAL); X } X dmafree(BMSCLOCK); X IENABLE(); X X return(r=0); X} X / -----------------------end here----------------------- Howard Johnson ATT Bell Labs ... lzaz!hcj
meulenbr@cst.UUCP (Frans Meulenbroeks) (11/13/88)
nice! thanks! I needed this, but didn't have the proper info to write the code myself. I noticed one problem though. It is explained below. Note: I removed lots of stuff from the original article, just saving enough context so one can repair. In article <264@lzaz.ATT.COM> hcj@lzaz.ATT.COM (HC Johnson) writes: >X> char *nayme[]= {"BMSCLK", "PRINTR", "TTY ", "WINCHE", "FLOPPY", "RAMDSK", "CLOCK ", >X====================================================================== >Xfs/table >Xh/com.h This line should not be here! remove it. >X54a55,60 >X> #define BMSCLOCK -9 /* clock on BMS 100 */ >X> # define BMS_READ 3 >X> # define BMS_WRITE 4 >X> >X> #define SERIAL -10 /* serial port */ >X> >X====================================================================== >Xh/const.h >X25,26c25,26 >X< #define NR_TASKS 8 /* number of tasks in the transfer vector */ >X< #define NR_PROCS 16 /* number of slots in proc table */ >X--- >X> #define NR_TASKS 9 /* number of tasks in the transfer vector */ >X> #define NR_PROCS 17 /* number of slots in proc table */ You'll need a line Xfs/table.c here. This is a patch in this file. (By the way: patch crashed on this point on an uncorrected file) >X127,130c127,134 >X< no_call, rw_dev, no_call, PRINTER /* 6 = /dev/lp */ >X< }; >X< What I missed after having this installed was a program to set the minix clock. I changed megartc.c to cope with both the mega and the bms clock. However, since I do not own a mega, and my BMS clock shows sometimes weird behaviour (I think it needs a new power pill), I am looking for one or a few persons who will test my changes. Both one or two mega and BMS testers are needed. Any volunteers?? -- Frans Meulenbroeks (meulenbr@cst.prl.philips.nl) Centre for Software Technology ( or try: ...!mcvax!philmds!prle!cst!meulenbr)