⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stick.pas

📁 DOS下的USB驱动源码,包括UHCI
💻 PAS
字号:
Program stick (output);

{This sample reads a sector from a USB memory stick using the "bulk
 only" protocol. Adapted from 'stick.bas' by Joe da Silva, to suit
 various real-mode compilers, such as Turbo Pascal 5.5 (available
 for free download from "http://bdn.borland.com/museum").  However,
 for TP/BP 7.0, be sure to use a non-Borland version of the CRT unit
 (or not at all), else you may encounter the infamous "RTE 200" bug.}

Uses
   dos,  {provides the "registers" type & "intr" routine}
   crt;  {provides the "clrscr" & "gotoxy" routines}

Const
   DosUsbInt = $65;     {interrupt used by DosUSB/DosUHCI driver}
   control_token = $2D; {transaction_token values ...}
   in_token = $69;
   out_token = $E1;
   command_token = $FF;
   devadd = 2; {1}      {device address assigned by DosUSB/DosUHCI}
   in_endpoint = 1;     {was 2}
   out_endpoint = 2;    {was 1}
   CR = ^M;
   LF = ^J;

Type
   dword = longint;

   URB_type =
      packed record
         transaction_token : byte; {see token values above}
         chain_end_flag  : byte; {1 = another URB follows this one in memory}
         dev_add         : byte;
         end_point       : byte;
         error_code      : byte;
         status          : byte; {returned by dosuhci}
         transaction_flags : word; {reserved}
         buffer_off      : word; {for in/out}
         buffer_seg      : word; {for in/out}
         buffer_length   : word; {for in/out}
         actual_length   : word; {for in/out}
         setup_buffer_off : word; {for control}
         setup_buffer_seg : word; {for control}
         start_frame     : word; {reserved}
         nr_of_packets   : word; {reserved - iso}
         int_interval    : byte; {reserved}
         error_count     : byte; {reserved}
         timeout         : word; {reserved}
         next_urb_off    : word; {reserved}
         next_urb_seg    : word; {reserved}
      end; {record, 32 bytes long}

   setup_type =
      packed record
         bmRequestType  : byte;
         bRequest	: byte;
         wValue		: word;
         wIndex		: word;
         wLength	: word;
      end; {record}

   read_command =
      packed record
         {first cbw fields 15 bytes}
         signature      : dword;
         tag            : dword;
         tlength        : dword;
         flags          : byte;
         cbwlun         : byte;
         clength        : byte;
         {now command fields 16 bytes}
         operation_code : byte;
         lun            : byte;
         lba            : dword;
         reserved       : byte;
         blocks         : word;
         controls       : byte;
         padding1       : word;
         padding2       : word;
         padding3       : word;
      end; {record, 31 bytes long}

   hexstring = string[8];
   buffer_type = packed array [1..64] of char;

Var
   urb : URB_type;
   device_request : setup_type;
   read_command_request : read_command;
   {inquiry_command_request : read_command;}
   buffer : buffer_type;
   sbuffer : packed array [1..1256] of char;
   ecode : integer;
   lba : dword;

(***************************************************************)

Function swap4endian (number : dword) : dword;
type
   dual_word =
      packed record
         first, second : word;
      end; {record}
var
   temp : dual_word;
begin {swap_endian}
   temp.first := swap(dual_word(number).second);
   temp.second := swap(dual_word(number).first);
   swap4endian := dword(temp);
end; {swap_endian}

Procedure writechars (var first : char; len : word; ln : boolean);
type
   bigstring = packed array [1..32000] of char;
var
   charptr : ^bigstring;
   i : integer;
begin {writechars}
   charptr := addr(first);
   for i := 1 to len do
      write(charptr^[i]);
   if ln
   then
      writeln;
end; {writechars}

Function hex2char (nibble : byte) : char;
{Form hex character from nibble value}
begin {hex2char}
   if nibble < 10
   then
      hex2char := chr(ord('0')+nibble)
   else
      hex2char := chr(ord('A')+nibble-10)
end; {hex2char}

Function hexstr (num : dword; digits : word) : hexstring;
var
   st : array [1..8] of char;
   i : word;
begin {hexstr}
   for i := digits downto 1 do
      begin {for}
         st[i] := hex2char(num mod 16);
         num := num div 16
      end; {for}
   hexstr := copy(st,1,digits);
end; {hexstr}

Procedure DosUHCI (var urb : URB_type; cmd_code : word);
{Call DosUHCI/DosUSB driver API.   Note, 'cmd_code' only
 applies when 'transaction_token' = command_token ($FF).}
var
   regs : registers;
begin {DosUHCI}
   urb.error_code := 0;
   regs.AX := cmd_code;
   regs.DS := seg(urb);
   regs.DX := ofs(urb);
   intr(DosUsbInt, regs);
   case urb.error_code of
      0 : {no error};
      1 : writeln('Error, invalid device address.');
      2 : writeln('Error, internal error.');
      3 : writeln('Error, invalid transaction_type.');
      4 : writeln('Error, invalid buffer length.')
   else
      writeln('Error, code = ',urb.error_code);
   end; {case}
end; {DosUHCI}

Function DosUHCIpresent : boolean;
const
   check_presence = 6;
   confirmation = $47;
var
   urb : URB_type;
   vector : pointer;
begin {DosUHCIpresent}
   {prepare for DosUHCI call, also initializes return code}
   urb.transaction_token := command_token;
   urb.dev_add := 0;  {driver-sensitive item, empirically determined}
   urb.buffer_length := 0; {driver-sensitive item, empirically determined}
   {call API, but first ensure int. vector is plausible}
   GetIntVec(DosUsbInt,vector);
   if seg(vector^) > $100
   then
      DosUHCI(urb,check_presence);
   DosUHCIpresent := (urb.transaction_token = confirmation);
end; {DosUHCIpresent}

Procedure EnableDebug (dev_addr : byte);
const
   enable_debug = 2;
var
   urb : URB_type;
begin {EnableDebug}
   urb.transaction_token := command_token;
   urb.dev_add := dev_addr;
   DosUHCI(urb,enable_debug);
end; {EnableDebug}

Procedure DisableDebug (dev_addr : byte);
const
   disable_debug = 3;
var
   urb : URB_type;
begin {DisableDebug}
   urb.transaction_token := command_token;
   urb.dev_add := dev_addr;
   DosUHCI(urb,disable_debug);
end; {DisableDebug}

Procedure InRequest (dev_id: byte; var urb: URB_type; var buf: buffer_type);
begin {InRequest}
   {set up In request}
   urb.transaction_token := in_token;
   urb.chain_end_flag := 0;
   urb.dev_add := dev_id;
   urb.end_point := in_endpoint;
   urb.error_code := 0;
   urb.status := 0;
   urb.transaction_flags := 0;
   urb.buffer_off := ofs(buf);
   urb.buffer_seg := seg(buf);
   urb.buffer_length := 64;
   urb.actual_length := 64;
   urb.setup_buffer_off := 0;
   urb.setup_buffer_seg := 0;
   urb.start_frame := 0;
   urb.nr_of_packets := 0;
   urb.int_interval := 0;
   urb.error_count := 0;
   urb.timeout := 0;
   urb.next_urb_off := 0;
   urb.next_urb_seg := 0;

   {now call DosUHCI/DosUSB}
   DosUHCI(urb,0);
end; {InRequest}

Procedure OutRequest (dev_id: byte; var urb: URB_type; var buf: buffer_type);
begin {OutRequest}
   {set up Out request}
   urb.transaction_token := out_token;
   urb.chain_end_flag := 0;
   urb.dev_add := dev_id;
   urb.end_point := out_endpoint;
   urb.error_code := 0;
   urb.status := 0;
   urb.transaction_flags := 0;
   urb.buffer_off := ofs(buf);
   urb.buffer_seg := seg(buf);
   urb.buffer_length := 31;
   urb.actual_length := 64;
   urb.setup_buffer_off := 0;
   urb.setup_buffer_seg := 0;
   urb.start_frame := 0;
   urb.nr_of_packets := 0;
   urb.int_interval := 0;
   urb.error_count := 0;
   urb.timeout := 0;
   urb.next_urb_off := 0;
   urb.next_urb_seg := 0;

   {now call DosUHCI/DosUSB}
   DosUHCI(urb,0);
end; {OutRequest}

Procedure CommandRequest (dev_id: byte; var urb: URB_type;
                      var buf: buffer_type; var dev_req : setup_type);
begin {CommandRequest}
   {set up Command request}
   urb.transaction_token := control_token;
   urb.chain_end_flag := 0;
   urb.dev_add := dev_id;
   urb.end_point := 0;
   urb.error_code := 0;
   urb.status := 0;
   urb.transaction_flags := 0;
   urb.buffer_off := ofs(buf);
   urb.buffer_seg := seg(buf);
   urb.buffer_length := 1;
   urb.actual_length := 8;
   urb.setup_buffer_off := ofs(dev_req);
   urb.setup_buffer_seg := seg(dev_req);
   urb.start_frame := 0;
   urb.nr_of_packets := 0;
   urb.int_interval := 0;
   urb.error_count := 0;
   urb.timeout := 0;
   urb.next_urb_off := 0;
   urb.next_urb_seg := 0;

   {now call DosUHCI/DosUSB}
   DosUHCI(urb,0);
end; {CommandRequest}

Procedure do_read (lbanumber : dword);
var
   i : integer;
   midpos : integer;
begin {do_read}
   {set up bulk read command incl. cbw}
   read_command_request.signature := $43425355;
   read_command_request.tag := $82A36008;
   read_command_request.tlength := $200; {512 bytes}
   read_command_request.flags := $80;
   read_command_request.cbwlun := 0; {1}
   read_command_request.clength := $0A;
   {now command fields}
   read_command_request.operation_code := $28;
   read_command_request.lun := 0; {32} {1}
   read_command_request.lba := swap4endian(lbanumber); {0} {big endian}
   {write('LBA:', hexstr(read_command_request.lba,8), ' ');}
   read_command_request.reserved := 0;
   read_command_request.blocks := swap($01); {00} {big endian}
   {writeln('Blocks:', hexstr(read_command_request.blocks,4));}
   read_command_request.controls := 0;
   read_command_request.padding1 := 0;
   read_command_request.padding2 := 0;
   read_command_request.padding3 := 0;

   move(read_command_request,buffer[1],64);

   OutRequest(devadd, urb, buffer);

   fillchar(buffer,64,chr(0)); {return data here}

   i := 0;
   while i < 8 {leave if 8 ( 8*64=512 )} do
      begin {while}

         InRequest(devadd, urb, buffer);

         if urb.status = 0
         then
            begin {then}
               inc(i);
               midpos := 1+(i-1)*64;
               move(buffer,sbuffer[midpos],sizeof(buffer));
            end {then}
         else
            if urb.status <> 88
            then
               exit; {do not incr. if 88}

      end; {while}
end; {do_read}

(***************************************************************)

Begin {stick}

   {revert console I/O from CRT to standard}
   assign(input,'');
   reset(input);
   assign(output,'');
   rewrite(output);
   {initialization start}
   if not DosUHCIpresent
   then
      begin {then}
         writeln(CR,LF,'Error : DosUHCI/DosUSB driver isn''t loaded.');
         halt(1);
      end; {then}
   {EnableDebug(devadd);}
   {DisableDebug(devadd);}
   ClrScr;
   fillchar(buffer,64,chr(0)); {return data here}
   fillchar(sbuffer,1256,chr(0)); {return data here}
   val(ParamStr(1), lba, ecode);
   if ecode <> 0
   then
      lba := 0; {543}
   writeln('LBA = ', lba, ' (Assumptions: USB device = ', devadd,
           ', In endpoint = ', in_endpoint,
           ', Out endpoint = ', out_endpoint, ')');
   {initialization end}

(* optional code ...
   {get max lun}
   device_request.bmRequestType := $A1;
   device_request.bRequest := $FE;
   device_request.wValue := $0000;
   device_request.wIndex := $0000;
   device_request.wLength := $0001;

   CommandRequest(devadd, urb, buffer, device_request);

   {transaction error?}
   if urb.status > 1
   then
      begin {then}
         ClrScr;
         gotoxy(14,23);
         writeln('Device does not respond');
      end; {then}

   write(CR,LF,'Logical units:');
   writechars(buffer[1],urb.actual_length,true);
... optional code *)

   {set up inquiry command incl. cbw}
   read_command_request.signature := $43425355;
   read_command_request.tag := $82A36008;
   read_command_request.tlength := $24;
   read_command_request.flags := $80;
   read_command_request.cbwlun := 0; {1}
   read_command_request.clength := $06;
   {now command fields}
   read_command_request.operation_code := $12;
   read_command_request.lun := 0; {32} {1}
   read_command_request.lba := $240000;
   read_command_request.reserved := 0;
   read_command_request.blocks := 0;
   read_command_request.controls := 0;
   read_command_request.padding1 := 0;
   read_command_request.padding2 := 0;
   read_command_request.padding3 := 0;

   move(read_command_request,buffer,sizeof(read_command_request));

   OutRequest(devadd, urb, buffer);

(* stick.bas: buffer=repeat$(100,chr$(0)) 'return data here
   !!! buffer is only 64 bytes, so 100 seems a bug ... *)

   fillchar(buffer,64,chr(0));

   InRequest(devadd, urb, buffer);

   write(CR,LF,'Inquiry:');
   writechars(buffer[1],urb.actual_length,true);

   {In request - to read CSW}
   InRequest(devadd, urb, buffer);

   write(CR,LF,'CSW:');
   writechars(buffer[1],urb.actual_length,true);

   do_read(lba);

   if urb.error_code > 0
   then
      begin
         ClrScr;
         gotoxy(14,23);
         writeln('Buffer length exceeded');
      end;

   writeln(CR,LF,'Sector (LBA): ',lba);
   writechars(sbuffer[1],512,true);

   {In request - to read CSW}
   InRequest(devadd, urb, buffer);

   write(CR,LF,'CSW:');
   writechars(buffer[1],urb.actual_length,true);
End. {stick}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -