|
|
1.1 ! root 1: /* ! 2: * qq - sample device driver using absolute memory addressing ! 3: * ! 4: * All this device does is read/write video ram. ! 5: * It assumes that there is a monochrome adapter in use, so that video ! 6: * ram starts at segment B000; if color, this should be changed to B800. ! 7: * ! 8: * This driver does not do anything useful; it is intended to serve as ! 9: * an example. ! 10: * ! 11: * Here is how to make the driver and test it (you will need a COHERENT ! 12: * Driver Kit installed on your system): ! 13: * 1. put this file, "qq.c", in /usr/src/sys/i8086/drv/qq.c ! 14: * 2. cut out the make file and store it in /usr/src/sys/i8086/drv/Mf.qq ! 15: * 3. cut out the config file and store it at /usr/sys/confdrv/qq ! 16: * 4. execute the following commands ! 17: * cd /usr/src/sys/i8086/drv ! 18: * make -f Mf.qq ! 19: * cd /usr/sys ! 20: * ldconfig qq ! 21: * drvld ldrv/qq ! 22: * 5. the driver should now be loaded - try "date > /dev/qq" or ! 23: * "cat < /dev/qq" (you will have to use Ctrl-C to stop the "cat" ! 24: * command) ! 25: * 6. to unload the driver, do "ps -d" to get the PID number for the driver; ! 26: * then do "kill kill nnn" where nnn is the process number for "<qq>" ! 27: */ ! 28: /**** ! 29: Here is the makefile for the "qq" driver (cut it out of this file): ! 30: --------------- cut here ----------------- ! 31: # Make file for a loadable driver ! 32: ! 33: AS=exec /bin/as ! 34: CC=exec /bin/cc ! 35: CPP=exec /lib/cpp ! 36: CFLAGS=-I.. -I../sys -I../.. -I../../sys \ ! 37: -I/usr/include/sys ! 38: AFLAGS=-gx ! 39: ! 40: # Include directories ! 41: USRINC=/usr/include ! 42: SYSINC=/usr/include/sys ! 43: KERINC=/usr/src/sys/sys ! 44: DRVINC=/usr/src/sys/i8086/sys ! 45: USRSYS=/usr/sys ! 46: ! 47: DRVOBJ= objects/qq.o ! 48: ! 49: qq: objects/qq.o ! 50: rm -f $(USRSYS)/lib/qq.a ! 51: ar rc $(USRSYS)/lib/qq.a objects/qq.o ! 52: ! 53: objects/qq.o: \ ! 54: $(KERINC)/coherent.h $(SYSINC)/types.h \ ! 55: $(SYSINC)/machine.h $(SYSINC)/param.h \ ! 56: $(SYSINC)/fun.h \ ! 57: $(SYSINC)/con.h \ ! 58: $(USRINC)/errno.h \ ! 59: $(SYSINC)/sched.h \ ! 60: $(SYSINC)/seg.h \ ! 61: $(SYSINC)/stat.h \ ! 62: $(SYSINC)/types.h \ ! 63: $(SYSINC)/uproc.h \ ! 64: qq.c ! 65: $(CC) $(CFLAGS) -c -o $@ qq.c ! 66: --------------- cut here ----------------- ! 67: ! 68: Here is the configuration file for the "qq" driver. ! 69: Cut it out of this file and copy it to "/usr/sys/confdrv/qq". ! 70: When "ldconfig" is run, it will create a node for /dev/qq. ! 71: --------------- cut here ----------------- ! 72: : ! 73: : 'Dummy driver for write to absolute RAM area' ! 74: : ! 75: UNDEF="${UNDEF} -u qqcon_ lib/qq.a" ! 76: PATCH="${PATCH} drvl_+70=qqcon_" ! 77: : ! 78: : devices ! 79: : ! 80: umask 0111 ! 81: /etc/mknod -f ${DEV-/dev}/qq c 7 0 || exit 1 ! 82: --------------- cut here ----------------- ! 83: ****/ ! 84: #include "coherent.h" ! 85: #include "ins8250.h" ! 86: #include <sys/stat.h> ! 87: #include <sys/uproc.h> ! 88: #include <sys/proc.h> ! 89: #include <sys/con.h> ! 90: #include <errno.h> ! 91: #include <sys/types.h> ! 92: #include <sys/mmu.h> ! 93: ! 94: /* ! 95: * Definitions. ! 96: * ! 97: */ ! 98: #define MONOVIDEO 0xB000 /* monochrome text RAM segment */ ! 99: #define VIDLENGTH (2048*2) /* screen locations (2 bytes each) */ ! 100: ! 101: /* ! 102: * Export Functions. ! 103: */ ! 104: int qqload(); ! 105: int qqopen(); ! 106: int qqclose(); ! 107: int qqread(); ! 108: int qqwrite(); ! 109: int qqunload(); ! 110: ! 111: /* ! 112: * Import Functions ! 113: */ ! 114: int nulldev(); ! 115: int nonedev(); ! 116: ! 117: /* ! 118: * Configuration table. ! 119: */ ! 120: CON qqcon ={ ! 121: DFCHR, /* Flags */ ! 122: 7, /* Major index */ ! 123: qqopen, /* Open */ ! 124: qqclose, /* Close */ ! 125: nulldev, /* Block */ ! 126: qqread, /* Read */ ! 127: qqwrite, /* Write */ ! 128: nulldev, /* Ioctl */ ! 129: nulldev, /* Powerfail */ ! 130: nulldev, /* Timeout */ ! 131: qqload, /* Load */ ! 132: qqunload, /* Unload */ ! 133: nulldev /* Poll */ ! 134: }; ! 135: ! 136: /* ! 137: * Local variables. ! 138: */ ! 139: static faddr_t screen_fp; /* (far *) to access screen */ ! 140: static paddr_t screen_base; /* physical address of screen base */ ! 141: ! 142: /* ! 143: * Load Routine. ! 144: */ ! 145: static qqload() ! 146: { ! 147: /* ! 148: * Allocate a selector to map onto the video RAM. ptov() will ! 149: * return the first available selector of the 8,192 possible. ! 150: * This is time consuming, so we only want to do this as part ! 151: * of our initialization code and not on every access. ! 152: * ! 153: * Since we are operating in 286 protected mode (ugh), the ! 154: * second argument to ptov() must not exceed 0x10000L. ! 155: */ ! 156: screen_base = (paddr_t)((long)(unsigned)MONOVIDEO << 4); ! 157: screen_fp = ptov(screen_base, (fsize_t)VIDLENGTH); ! 158: } ! 159: ! 160: static qqunload() ! 161: { ! 162: /* ! 163: * We have to free up the selector now that we're done using it. ! 164: */ ! 165: vrelse(screen_fp); ! 166: } ! 167: ! 168: /* ! 169: * Open Routine. ! 170: */ ! 171: qqopen( dev, mode ) ! 172: dev_t dev; ! 173: { ! 174: } ! 175: ! 176: /* ! 177: * Close Routine. ! 178: */ ! 179: qqclose( dev ) ! 180: dev_t dev; ! 181: { ! 182: } ! 183: ! 184: /* ! 185: * Read Routine. ! 186: */ ! 187: qqread( dev, iop ) ! 188: dev_t dev; ! 189: register IO * iop; ! 190: { ! 191: static int offset; ! 192: int c; ! 193: /* ! 194: * Read a character code from video RAM ! 195: * Start reading RAM just after where previous read ended ! 196: * ! 197: * Note that "offset" is the value of the displacement into ! 198: * the screen RAM. Any expression which results in a value ! 199: * which is less than VIDLENGTH is OK here. ! 200: */ ! 201: while(iop->io_ioc) { ! 202: c = ffbyte(screen_fp + offset); /* fetch a "far" byte */ ! 203: if(ioputc(c, iop) == -1) ! 204: break; ! 205: offset += 2; ! 206: offset %= VIDLENGTH; ! 207: } ! 208: } ! 209: ! 210: /* ! 211: * Write Routine. ! 212: */ ! 213: qqwrite( dev, iop ) ! 214: dev_t dev; ! 215: register IO * iop; ! 216: { ! 217: int offset = 0; ! 218: int c; ! 219: ! 220: /* ! 221: * Write a character into the screen RAM ! 222: * Note that "offset" is the value of the displacement into ! 223: * the screen RAM. Any expression which results in a value ! 224: * which is less than VIDLENGTH is OK here. ! 225: */ ! 226: while ((c = iogetc(iop)) >= 0 && offset < VIDLENGTH) { ! 227: sfbyte(screen_fp + offset, c); /* store a "far" byte */ ! 228: offset += 2; /* skip attribute byte */ ! 229: } ! 230: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.