|
|
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: qq.c ! 64: $(CC) $(CFLAGS) -c -o $@ qq.c ! 65: --------------- cut here ----------------- ! 66: ! 67: Here is the configuration file for the "qq" driver. ! 68: Cut it out of this file and copy it to "/usr/sys/confdrv/qq". ! 69: When "ldconfig" is run, it will create a node for /dev/qq. ! 70: --------------- cut here ----------------- ! 71: : ! 72: : 'Dummy driver for write to absolute RAM area' ! 73: : ! 74: UNDEF="${UNDEF} -u qqcon_ lib/qq.a" ! 75: PATCH="${PATCH} drvl_+70=qqcon_" ! 76: : ! 77: : devices ! 78: : ! 79: umask 0111 ! 80: /etc/mknod -f ${DEV-/dev}/qq c 7 0 || exit 1 ! 81: --------------- cut here ----------------- ! 82: ****/ ! 83: #include "coherent.h" ! 84: #include "ins8250.h" ! 85: #include <sys/stat.h> ! 86: #include <sys/uproc.h> ! 87: #include <sys/proc.h> ! 88: #include <sys/con.h> ! 89: #include <errno.h> ! 90: #include <sys/types.h> ! 91: #include <sys/mmu.h> ! 92: ! 93: /* ! 94: * Definitions. ! 95: * ! 96: */ ! 97: #define MONOVIDEO 0xB000 /* monochrome text RAM segment */ ! 98: #define VIDLENGTH (2048*2) /* screen locations (2 bytes each) */ ! 99: ! 100: /* ! 101: * Export Functions. ! 102: */ ! 103: int qqload(); ! 104: int qqopen(); ! 105: int qqclose(); ! 106: int qqread(); ! 107: int qqwrite(); ! 108: int qqunload(); ! 109: ! 110: /* ! 111: * Import Functions ! 112: */ ! 113: int nulldev(); ! 114: int nonedev(); ! 115: ! 116: /* ! 117: * Configuration table. ! 118: */ ! 119: CON qqcon ={ ! 120: DFCHR, /* Flags */ ! 121: 7, /* Major index */ ! 122: qqopen, /* Open */ ! 123: qqclose, /* Close */ ! 124: nulldev, /* Block */ ! 125: qqread, /* Read */ ! 126: qqwrite, /* Write */ ! 127: nulldev, /* Ioctl */ ! 128: nulldev, /* Powerfail */ ! 129: nulldev, /* Timeout */ ! 130: qqload, /* Load */ ! 131: qqunload, /* Unload */ ! 132: nulldev /* Poll */ ! 133: }; ! 134: ! 135: /* ! 136: * Local variables. ! 137: */ ! 138: static faddr_t screen_fp; /* (far *) to access screen */ ! 139: static paddr_t screen_base; /* physical address of screen base */ ! 140: ! 141: /* ! 142: * Load Routine. ! 143: */ ! 144: static qqload() ! 145: { ! 146: /* ! 147: * Allocate a selector to map onto the video RAM. ptov() will ! 148: * return the first available selector of the 8,192 possible. ! 149: * This is time consuming, so we only want to do this as part ! 150: * of our initialization code and not on every access. ! 151: * ! 152: * Since we are operating in 286 protected mode (ugh), the ! 153: * second argument to ptov() must not exceed 0x10000L. ! 154: */ ! 155: screen_base = (paddr_t)((long)(unsigned)MONOVIDEO << 4); ! 156: screen_fp = ptov(screen_base, (fsize_t)VIDLENGTH); ! 157: } ! 158: ! 159: static qqunload() ! 160: { ! 161: /* ! 162: * We have to free up the selector now that we're done using it. ! 163: */ ! 164: vrelse(screen_fp); ! 165: } ! 166: ! 167: /* ! 168: * Open Routine. ! 169: */ ! 170: qqopen( dev, mode ) ! 171: dev_t dev; ! 172: { ! 173: } ! 174: ! 175: /* ! 176: * Close Routine. ! 177: */ ! 178: qqclose( dev ) ! 179: dev_t dev; ! 180: { ! 181: } ! 182: ! 183: /* ! 184: * Read Routine. ! 185: */ ! 186: qqread( dev, iop ) ! 187: dev_t dev; ! 188: register IO * iop; ! 189: { ! 190: static int offset; ! 191: int c; ! 192: /* ! 193: * Read a character code from video RAM ! 194: * Start reading RAM just after where previous read ended ! 195: * ! 196: * Note that "offset" is the value of the displacement into ! 197: * the screen RAM. Any expression which results in a value ! 198: * which is less than VIDLENGTH is OK here. ! 199: */ ! 200: while(iop->io_ioc) { ! 201: c = ffbyte(screen_fp + offset); /* fetch a "far" byte */ ! 202: if(ioputc(c, iop) == -1) ! 203: break; ! 204: offset += 2; ! 205: offset %= VIDLENGTH; ! 206: } ! 207: } ! 208: ! 209: /* ! 210: * Write Routine. ! 211: */ ! 212: qqwrite( dev, iop ) ! 213: dev_t dev; ! 214: register IO * iop; ! 215: { ! 216: int offset = 0; ! 217: int c; ! 218: ! 219: /* ! 220: * Write a character into the screen RAM ! 221: * Note that "offset" is the value of the displacement into ! 222: * the screen RAM. Any expression which results in a value ! 223: * which is less than VIDLENGTH is OK here. ! 224: */ ! 225: while ((c = iogetc(iop)) >= 0 && offset < VIDLENGTH) { ! 226: sfbyte(screen_fp + offset, c); /* store a "far" byte */ ! 227: offset += 2; /* skip attribute byte */ ! 228: } ! 229: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.