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!hcjmeulenbr@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)