zoukankan      html  css  js  c++  java
  • (莱昂氏unix源代码分析导读-50)LP11行式打印机

                                                                by cszhao1980


    LP11有两个设备寄存器:状态寄存器(lpsr)和数据缓冲寄存器(lpbuf),可通过以下结构进行访问:

    8812: #define LPADDR 0177514

    8823: struct {

    8824:     int lpsr;

    8825:     int lpbuf;

    8826: };

     

    1.  LPADDR.lpsr:状态寄存器

    i. 15位(最高位):出错标记;

    如电源未开、缺纸、温度太高等都会造成标志置位。

    判断条件: LPADDR.lpsr < 0

     

    ii. 7位: DONE标记(当该打印机控制器准备接收下一字符时设置);

              

    iii. 6位: Enable标记,设置后才启动了该打印机,其作用是使“DONE”或“ERROR”造成一中断。

     

    2. LPADDR.lpbuf:数据缓冲寄存器

    6至第0位保存要打印字符的7ASCII代码,对此寄存器只能执行写操作。

     

    除此之外,unix v6使用struct lp11来维护LP11设备信息,如下所示:

    8829: struct {

    8830:     int cc;    //前三个字用作缓冲头,即起到struct clist的作用。

    8831:     int cf;   

    8832:     int cl;    

    8833:     int flag;   //记录LP11的工作状态信息

    8834:     int mcc;

    8835:     int ccc;

    8836:     int mlc;

    8837: } lp11;

     

    1 LP11的工作方式

    【注】:莱昂书中并没有详细介绍LP11的工作方式——它实在是一种简单的设备,而且,在当时

                    也可能很常用。本章的部分内容是通过代码所进行的合理的推测。

     

    首先, LP11设备拥有一个缓存区域,用来存放要打印的内容。向LP11发送数据是通过设置LPADDR.

    lpbuf进行的,当我们设置LPADDR.lpbuf后,其内容会被LP11以很快的速度(超过CPU存放速度)存放

    在其内部的缓存区域内。当LP11无法再接收数据时,会将DONE标记复位,此时,不应再向LP11发送数据。

     

    LP11收到足够多的数据后(也许是达到一整行的内容后),会启动打印操作。操作结束后,会通过中断

    矢量200进入中断处理程序lpint

    2 LP11驱动程序

    了解了LP11的工作方式之后,其驱动程序就很容易理解了。

    openclose代码都非常简单,在这里不再多解释了。唯一需要注意的是open时对“OPENflag的检查和设置,

    这些代码实现了unix v6LP11设备的互斥访问。

     

    下面,我们来看一下其打印(write)过程。前面说过,write会通过writei函数调用到设备的实际write函数,对

    LP11来说,是lpwrite

     

    8870: lpwrite()

    8871: {

    8872:     register int c;

    8873:

    8874:     while ((c=cpass())>=0)     //从用户空间内取要打印的数据

    8875:         lpcanon(c);           //简单起见,我们暂时将其看作一个lpoutput调用

    8876: }

     

    8986: lpoutput(c)

    8987: {

    8988:     if (lp11.cc >= LPHWAT)     //lp11起到clist的作用,cc为字符缓冲区内的char的数量。

    8989:          sleep(&lp11, LPPRI);   //最多存放LPHWAT个,否则睡眠

    8990:     putc(c, &lp11);             //向字符缓冲区放置char

    8991:     spl4();

    8992:     lpstart();                   //启动真正的LP11驱动程序lpstart

    8993:     spl0();

    8994: }

     

    lpstart非常简单,即在DONE标记置位时,从字符缓冲区取字符发送给LP11设备。

     

    8967: lpstart()

    8968: {

    8969:      register int c;

    8970:

    8971:      while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0)

    8972:              LPADDR->lpbuf = c;

    8973: }

     

    中断处理程序lpint也非常简单,如下所示:

    8976: lpint()

    8977: {

    8978:     register int c;

    8979:

    8980:     lpstart();

    8981:     if (lp11.cc == LPLWAT || lp11.cc == 0)

    8982:           wakeup(&lp11);

    8983: }

     

    lpcanonLP11驱动程序中最长的一个,莱昂对其有详细的讲解,再次不再赘述。

    博客地址:http://blog.csdn.net/cszhao1980

    博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

  • 相关阅读:
    Unique ID Generate Notes
    My Apple Developer Library Catalog
    Flickr Hosts
    JqGrid 使用方法详解
    动态加载JS代码
    如何让Asp.net webAPI返回JSON格式数据
    谷歌(Chrome)安装Advanced REST Client插件
    .net chart(图表)控件的使用-System.Windows.Forms.DataVisualization.dll
    ASP.NET伪静态 UrlRewrite(Url重写) 实现和配置
    WebService开发常用功能详解
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3265419.html
Copyright © 2011-2022 走看看