首先要说明的是,该驱动程序仅实现了部分块设备的功能,如果作为成品软件使用,会感觉性能比较差,而且有些功能(比如FORMAT)是不能完成的,发表此驱动程序的目的旨在说明USB的编程原理以及DOS下驱动程序的工作原理;同时要说明的是,此驱动程序仅支持32M(包括32M)以下的U盘,当然这个问题解决起来并不困难,有兴趣的读者可以在阅读本文并理解的基础上加以改进使其支持32M以上2G以下的U盘。
  前面的博文中提到由于DOSUSB是在命令行加载的,如果从config.sys中加载这个基于DOSUSB的U盘驱动程序,那么驱动程序将先于DOSUSB被加载,使得这个驱动程序在初始化阶段无法使用DOSUSB,所以也就无法完成初始化,为此,专门写有一篇题为从命令行加载设备驱动程序的文章,试图解决这个问题,该文编写了一个简单的从命令行加载设备驱动程序的程序,遗憾的是,使用这篇文章中的程序加载本文的驱动程序,会出现一些莫名其妙的问题(比如使用dir时只能显示一个文件),这个程序是从另一个成品软件中简化而来的,看来在简化过程中没有处理好某一个细节,所以,从命令行加载本文的U盘驱动程序时,请使用下面程序(恕不提供源程序):http://blog.hengch.com/software/devload.com

  后面,我还会针对加载问题做详细说明。本文所涉及的源代码在下面地址下载:http://blog.hengch.com/source/udisk.rar 编译是要编译成com文件格式,如果使用masm6.11进行编译,可以使用里面的a.bat。
  这个驱动程序完成的块设备命令如下:
  • Command 00 ---- Initialization,初始化命令。
  • Command 01 ---- Media Check,介质检查。
  • Command 02 ---- Get BPB,得到BPB表
  • Command 04 ---- Input,读扇区。
  • Command 08 ---- Output,写扇区
  • Command 09 ---- Output Verify,带校验写扇区
  • Command 15 ---- Removable,可移动的存储介质
    下面就已经实现的命令做一个简要说明,以下部分涉及的请求头的数据结构,请自行参阅《如何写DOS下的设备驱动程序(三)》
  • Command 00 ---- 初始化命令
    标号:Initialization
    此命令在所有实现的命令中可以说是最复杂的一个。由于此命令仅在驱动程序被加载时调用一次,所以在驱动程序加载后可以将其占用的内存释放掉,为此,该命令的代码写在源程序的最后。
    该命令的实现包括以下步骤:
    Step 01:检查DOSUSB是否已经安装:简单地检查int 65h的中断向量是否为0,来判断DOSUSB是否安装,这个判断非常不严谨,如果读者需要,可以自行改进。
    Step 02:搜索USB设备:这部分属于PCI编程的范畴,读者可以自行参考文章《USB系列之一:列出你的USB设备》。我们在找到USB设备后,首先要从它的CLASS上判断是不是一个U盘,如果不是,找下一个USB设备,直到找到U盘设备;找到U盘后还要判断U盘设备的类型,本驱动程序仅支持OHCI,但由于EHCI可以用OHCI的方式驱动,所以也可以用在EHCI上,但不能用在UHCI上。
    Step 03:得到USB设备的设备描述符:读出设备描述符是为了下面读出更多的描述符,请自行参考文章《USB系列之二:读取USB设备的描述符》和《USB系列之五:用汇编实现的一些USB功能
    Step 04:得到USB设备的配置描述符:参考文章同上。读出USB设备的端点描述符后,要记录一些必要的数据,在后面读写U盘时要用,具体内容见源程序。
    Step 05:从调用驱动程序的请求头中得到可用的驱动器字母
    Step 06:复位
    Step 07:获取设备的最大逻辑单元号
    Step 08:检查设备是否就绪
    Step 09:获得U盘的容量
    Step 10:读出U盘上的主引导记录:有关主引导记录(MBR)、分区引导记录(DBR)等内容请参阅《如何写DOS下的设备驱动程序(三)
    Step 11:从主引导记录中分离出分区信息表并找到DOS分区
    Step 12:从U盘上读出分区引导记录
    Step 13:从分区引导记录中分离出BPB
    Step 14:填写请求头中的返回值
      Step 14-1:计算驱动程序驻留部分的长度返回驻留部分结尾处的地址
      Step 14-2:在请求头中返回设备单元数
      Step 14-3:返回BPB的地址指针
    Step 15:初始化结束返回
  • Command 01 ---- 介质检查
    标号:media_check
    尽管U盘可能是可更换介质的,但该驱动程序中忽略了这个特点,简单地永远返回“介质没有更换”的标志。
  • Command 02 ---- 得到BPB
    标号:get_bpb
    从U盘上重新读出BPB表,并把指针通过请求头返回
  • Command 09 ---- 带校验的写扇区
    如果是需要校验,只需要在写入后再读一遍,并把读出内容返回,所以实际上是使用了Command 04和Command 08。
  • Command 15 ---- 可移动的存储介质
    按照规范,如果介质是可移动的,请求头中的状态字的BUSY位必须置0,我们不管是否有可移动介质,始终把状态字节的BUSY位置1,强调介质不可移动,实际上是忽略了介质的可移动性。
  至此,这个驱动程序的大概情况就说明完了,这个程序的综合性较强,希望搞明白的读者希望在阅读本文前能够先搞懂《USB系列一》至《USB系列五》,以及《如何写DOS下设备驱动程序》之一、二、三,还要搞懂一些DOS内部的数据结构,这方面的文章在“DOS资料”分类中,总之是挺麻烦的。
  驱动程序的调试也是十分麻烦的,以后有机会介绍。
  该文介绍的驱动程序的加载过程如下:
  1、启动DOSUSB,请参阅文章《USB系列之二:读取USB设备的描述符》的相关部分
  2、使用文章开头下载的devload程序加载本文介绍的驱动程序UDISK.SYS
       devload udisk.sys

  再次声明,本文旨在介绍DOS下驱动程序的编写方法,以及USB编程原理,本文发布的驱动程序并不是成品软件,其中有很多已知的问题和不足,而且性能也比较差,仅作交流使用,作者不对使用该驱动产生的后果负责。

USB系列之六:基于DOSUSB的简单U盘驱动程序的更多相关文章

  1. USB系列之三:从你的U盘里读出更多的内容

    U盘是我们最常使用的一种USB设备,本文继续使用DOSUSB做驱动,试图以读取扇区的方式读取你的U盘.本文可能涉及的协议可能会比较多. 一.了解你的U盘    首先我们用上一篇文章介绍的程序usbvi ...

  2. (7)基于hadoop的简单网盘应用实现3

    一.login.jsp登陆界面实现 解压bootmetro-master.zip,然后将\bootmetro-master\src\下的assets目录复制到project里. bootmetro下载 ...

  3. USB系列之九:基于ASPI的U盘驱动程序

    USB系列之七和之八介绍了ASPI,并通过一些实例说明了基于ASPI的编程方法,本文使用前两篇文章介绍的知识以及以前介绍的有关DOS驱动程序下驱动程序的内容实际完成一个简单的基于ASPI的U盘驱动程序 ...

  4. USB系列之七:ASPI介绍及命令测试

    在以前的一篇博文<关于构建DOS下编程平台的总结>中曾经介绍了一种在DOS下驱动U盘的方法,我们大致回顾一下.在config.sys中加入两个驱动程序,就可以驱动U盘:device = a ...

  5. USB系列之八:透过ASPI执行SCSI命令

    在<USB系列之七>里我们介绍了ASPI的规范,并对一系列ASPI的命令做了测试,其中的02号命令是执行SCSI命令,我们专门在这篇文章中介绍,在<USB系列七>中,我们已经了 ...

  6. USB系列之五:用汇编实现的一些USB功能

    前面的USB系列一至四,实现了我们需要的一些USB功能,但都是用C语言的32位代码,之后我们插进了三篇关于DOS下设备驱动程序的文章,我们现在应该清楚,当我们要在DOS下写一个U盘的驱动时,最好使用汇 ...

  7. USB系列之四:向U盘上写数据

    在<USB系列之三>中,我们实现了一系列的SCSI命令,在这个系列中,我们要实现向U盘上写扇区的命令,所以,本文相对比较容易,更多地是给出一个实现的源程序. 在<USB系列之三> ...

  8. Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  9. USB系列之二:读取USB设备的描述符

    在前面的文章中,我们已经给出了USB协议的链接地址,从这篇文章起,我们会涉及到许多USB 1.1的内容,我们的指导思想是先从熟悉USB 1.1协议入手,先使用现成的HCD和USBD,直接面对客户端驱动 ...

随机推荐

  1. #Java编程题-百钱百鸡

    问题: 百钱百鸡问题.用100钱买100只鸡,公鸡一只五钱,母鸡一只三钱,雏鸡三只一钱,编程计算共有几种买法(要求每种鸡至少要买1只). 自己的实现,没有什么数据结构,算法,求大神指点!! packa ...

  2. BZOJ 1068 (区间DP)

    题意:字符串的压缩,f[l][r][0]代表还没M,f[l][r][1]代表有M. #include<cstdio> #include<cmath> #include<c ...

  3. WINDOWS 2012忘记密码之后。。。

    要使用windows server 2012安装DVD,选择光盘引导进入 进入修复系统 选择疑难解答,进入界面 选择命令提示符 切换目录至系统目录 执行move命令 执行 copy命令 重新启动系统, ...

  4. 使用OpenSSL生成证书

    使用OpenSSL生成证书 下载安装openssl,进入/bin/下面,执行命令(把ssl目录下的openssl.cnf 拷贝到bin目录下)1.首先要生成服务器端的私钥(key文件):openssl ...

  5. MySQL强制性操作

    1.强制索引FORCE INDEX SELECT * FROM TABLE1 FORCE INDEX (FIELD1) … 只使用建立在FIELD1上的索引,而不使用其它字段上的索引. 2.忽略索引 ...

  6. RAID,mdadm(笔记)

    RAID: 级别:仅代表磁盘组织方式不同,没有上下之分:0: 条带    性能提升: 读,写    冗余能力(容错能力): 无    空间利用率:nS    至少2块盘1: 镜像    性能表现:写性 ...

  7. Unable to resolve target 'android-14' 解决办法

    学习安卓的时候用Eclipse导入工程之后出现Unable to resolve target 'android-14' 这样的问题,代码确定没有问题,因为是从网上教程下载的示例代码,上网搜索了一下, ...

  8. hdu 4923 Room and Moor (单调栈+思维)

    题意: 给一个0和1组成的序列a,要构造一个相同长度的序列b.b要满足非严格单调,且 值为0到1的实数.最后使得  sum((ai-bi)^2)最小. 算法: 首先a序列開始的连续0和末尾的连续1是能 ...

  9. servlet基本概念

    一.servlet是一个供其它java程序调用的java类,比方tomcatserver,它不能独自执行,它的执行由servlet引擎来控制和调度. 二.servlet是单例,多线程 针对多个clie ...

  10. OCR怎么能离开扫描仪呢?

    说起OCR,说来说去就是和各种各样的图片打交道. 所以图片的质量很的关键. 说起图片的质量,不得不提的就是图片的採集. 眼下最靠谱的图像採集来源就是扫描仪. 扫描仪的话就大有说法,最靠谱的扫描仪,扫描 ...