[haiku-development] Re: xicon and executable scripts

  • From: Richard Jasmin <jasminr@xxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 07 May 2009 22:39:38 -0400

Ticket #824 :
[solution]

check your floppy code.spin the drive down and stop the motor.
you are supposed to do this on access, maybe it is the boot code, but it
shouldn't invert the drive access routines.THESE I have in Pascal.
[thanks to numerous GPL donors].

nevermind the stray characters, they are otherwise invisible. 
int24 is [at least in dos] a critical IO handler, which for project FPOS
is handled in the kernels isr (interrupt service request) routines.
MY floppy drive is usb, so I cannot test this code, yet anyway.

see below:
[I know,in Pascal but translation should prove too difficult...]

type
 
    drive_type:array[0..5] of string=('no floppy drive', 
'360kb 5.25in floppy drive', 
'1.2mb 5.25in floppy drive', 
'720kb 3.5in', 
'1.44mb 3.5in', 
'2.88mb 3.5in' )

    end;

  THardDiskParam = record
    Cylinders: LongWord;
    Heads: LongWord;
    Sectors: LongWord;
  end;

  THardDiskPorts = (
    Data:=$1F0,
    Error,        { $1F1 }
    SectorCount,  { $1F2 }
    SectorNumber, { $1F3 }
    LowCylinder,  { $1F4 }
    HighCylinder, { $1F5 }
    Head,         { $1F6 }
    Status,       { $1F7 }
    Command       { $1F7 }
  );

  THardDiskCommands = (
    ReadHD:=$20,
    WriteHD:=$30
  );
    JmpRec=record       { The starting jump in the bootsector }
  Code:byte; { $E9 XX XX / $EB XX XX}
  case byte of
   0:(Adr1:byte; NOP:byte);
   1:(Adr2:word);
 end;
 BpbRec=record       { The Bios Data Block (returned by DOS, and stored
in }
 BytesPSec:word;    { the bootsector }  SecPClus:byte;
  ResSec:word;
  NrFATs:byte;
  NrROOT:word;
  TotalSec:word;
  MDB:byte;
  SecPFAT:word;
  SecPSpoor:word;
  NrHead:word;
  HidSec32:longint;
  TotalSec32:longint;
 end;
 BootSec=record      { The bootsector format in DOS }
  JmpCode:JmpRec;
  Name:array[0..7] of char; { Isn't meaningfull at all, just FORMAT prg
name }
  Bpb:BpbRec;
 end;
 BootSecP=^BootSec;



var
  buf:array [1..512]of byte;
  ch:char;
  S:string[1]; { To store driveletter }
  I:byte;
  BigPart:boolean;                 { 32-bit sectors? }
  Drive:byte;                      { which drive are we using }
  ROOTSec,FATSec,DataSec:longint;  { Some starting sectors }
  FAT12:boolean;                   { 12-bit FAT? }
  LastSecNo:longint;               { Save last sector number... }
  LastError:word;                  { ... and error code for error
report }
  MotorState : byte = 0;
  Ticks : byte;
  Waiting : boolean;
  Size : LongWord;
  {$Align 32}
  Buffer : array[1..$4800] of byte;
  regs:tregisters;

const

    SizeBpb=SizeOf(BpbRec);
 { Needed for assembly part, AFAIK you can't get the size of a
structure }
 { (record) in an asm..end; block (shame on you, Borland (or on
me :-) )) }

  StatusRegA : word = $0000;  // Read Only
  StatusRegB : word = $0001;  // Read Only
  DOReg : word = $0002;
  TapeDrvReg : word = $0003;
  MSReg : word = $0004; // Read Only - Main Status Reg
  FIFOReg : word = $0005; // Write-only
  DIReg : word = $0007;      // Read Only
  CCReg : word = $0007; // Write-only

  MotorOnDelay : integer = 50;
  MotorOffDelay : integer = 300;
  DMAChan : byte = 2;
  DMABufLen : word = $4800;

procedure FloppyWriteCmd(Drive : byte; cmd : byte);
function FloppyReadCmd(Drive : byte) : byte; 
procedure SenseInt(Drive : byte; var st0, cyl : byte);
function Calibrate(Drive : byte) : byte;
function Seek(Drive : byte; cyli, head : byte) : byte;
function FloppyReset(Drive : byte) : byte;
procedure Motor(Drive : byte; State : byte);
function FloppyDoTrack(Drive : byte; cyl : byte; dir : byte) : byte;
function FloppyDoTrackLBA(Drive : byte; LBA : byte; dir : byte;
NoSectors : byte) : byte;


procedure detectFloppys;
//pulled from C --Jazz
var
 a,b,c:char;

begin
writeportb($70, $10);
c = readportb($71);

a := c shr 4; // get the high nibble
b := c and $F; // get the low nibble by ANDing out the high nibble

write("Floppy drive A is a: ");
writeln(drive_type[a]);
write("Floppy drive B is a: ");
writeln(drive_type[b]);
writechar(#10);

end;


procedure LBA2CHS(LBA:LongWord; var cyl,head,sec : byte);
begin
sec := (LBA mod 18) + 1;
cyl := LBA Div 36;
head := (LBA Div 18) mod 2;
end;


procedure FloppyWriteCmd(Drive : byte; cmd : byte);
var
base : word;
i : integer;
begin
base := DriveBase[Drive];

repeat
Delay(100);
until(($C0 and ReadPortb(base + MSReg)) <> $C0);

for i := 1 to 300 do
  begin
  if (($C0 and ReadPortb(base + MSReg)) = $80) then
        begin
          WritePortb((Base + FIFOReg), cmd);
          Exit;
        end;
    Delay(100);
  end;
WriteLn('Floppy drive write command : Timeout');

end;

function FloppyReadCmd(Drive : byte) : byte;
var
base : word;
i : integer;
begin
base := DriveBase[Drive];

repeat
Delay(100);
until(($C0 and ReadPortb(base + MSReg)) <> $80);   

for i := 1 to 300 do
  begin
      if (($80 and ReadPortb(base + MSReg)) = $80) then
        begin
        FloppyReadCmd := ReadPortb(base + FIFOReg);
        Exit;
        end;
      Delay(100);
  end;
WriteLn('Floppy drive read command : Timeout');
FloppyReadCmd := 0;
end;

procedure IRQwait(no : byte);
begin
while Waiting = true do
end;


procedure SenseInt(Drive : byte; var st0, cyl : byte);
var
base : word;
begin
base := DriveBase[Drive];

FloppyWriteCmd(Drive, FloppyCmd[7]);
Delay(500);

st0 := FloppyReadCmd(Drive);
cyl := FloppyReadCmd(Drive);
end;

procedure Motor(Drive : byte; State : byte);
var
base : word;
begin
base := DriveBase[Drive];
// 0 - Off; 1 - On; 2 - Wait

if State = 1 then
  begin
// If requested on
if MotorState = 0 then
  begin
    //Turn motor on
    WritePortb(base + DOReg, $1C);
    Delay(MotorOnDelay);
    MotorState := 1;
  end
else
  begin
    if MotorState = 2 then
     // WriteLn(#10'Floppy Motor: Strange, motor already waiting');

    Ticks := 300;
    Delay(Ticks);
    MotorState := 2;
  end;
end;

if State = 0 then
if MotorState = 1 then
  begin
    WritePortb(base + DOReg, $0C);
    MotorState := 0;
    Delay(MotorOffDelay);
  end;
end;

function Calibrate(Drive : byte) : byte;
var
i, st0, cyl : byte ;
s : string;
begin
st0 := -1;
cyl := -1;

WriteLn(#10'Calibrating floppy drive...');

Motor(Drive, 1);

for i:= 0 to 10 do
  begin
    Waiting := True;
    FloppyWriteCmd(Drive, FloppyCmd[6]);
    FloppyWriteCmd(Drive, Drive);
    IrqWait(6);
    SenseInt(Drive, st0, cyl);

    if (st0 and $C0) = $C0 then
      WriteLn(#10'Floppy Calibrate : Status =' + DriveStatus[st0 shr
6]);   //Calibration error

    if cyl = 0 then
      begin
      Motor(Drive, 0);
      Calibrate := 0;
      WriteLn(#10'Floppy calibration done');
      Exit;
      end;
  end;
WriteLn('Floppy calibrate : Timeout');
Motor(Drive, 0);
Calibrate := 1;
end;

function FloppyReset(Drive : byte) : byte;
var
base : word;
st0, cyl : byte;
begin
st0 := -1;
cyl := -1;

Waiting := True;

base := DriveBase[Drive];

WritePortb(base + DOReg, $00);
WritePortb(base + DOReg, $0C);

IrqWait(6);
SenseInt(Drive, st0, cyl);

//Set transfer speed
WritePortb(base + CCReg, $00);

FloppyWriteCmd(Drive, FloppyCmd[2]);
FloppyWriteCmd(Drive, $DF);
FloppyWriteCmd(Drive, $02);

if Calibrate(Drive) = 1 then
  FloppyReset := 1
else
  FloppyReset := 0;
end;


function Seek(Drive : byte; cyli, head : byte):byte; //floppy seek
var
st0, cyl, i : byte;
s : string;
begin
st0 := -1;
cyl := -1;

Motor(Drive, 1);

for i := 0 to 10 do
  begin
  Waiting := True;
  FloppyWriteCmd(Drive, FloppyCmd[12]);
  FloppyWriteCmd(Drive, (head shl 2));
  FloppyWriteCmd(Drive, cyli);
  IRQWait(6);
  SenseInt(Drive, st0, cyl);

  if (st0 and $C0) = $C0 then
      WriteLn(#10'Floppy Seek: Status = ' + DriveStatus[st0 shr
6]);   //Calibration error

  if cyl = cyli then
    begin
      Motor(Drive,0);
      //WriteLn(#10'Cylinder Found'); ok, we found it, read or write it.
      
      Seek := 0;
      Exit;
    end;
  end;
Seek := -1;
Motor(Drive, 0);
WriteLn('Floppy Seek : Timeout');
end;

procedure FloppyDMAInit(dir : byte; Size : LongWord);
var
Addr, Count : Longword;
mode : byte;
begin

Addr := PtrUInt(@Buffer);
Count := Size - 1;

//enable DMA 2
//and setup buffer of 512 byte.

if (Addr and $ff000000) or (Count and $ffff0000) or ((Addr + Count) and
$ffff0000) <> (Addr and $ffff0000) then
    WriteLn('Floppy DMA: Static buffer problem');

//tells where to assign the buffer...

mode := $40;
mode := mode or $02;

case dir of
1  : mode := mode or $04; //Read to mem
2  : mode := mode or $08; //Write from mem
end;

WritePortb($0A,$06); //Mask DMA 2
WritePortb($0C,$FF); //Reset Flip-Flop

WritePortb($04,(Addr and $000000FF));         //Address Low byte
WritePortb($04,((Addr shr 8) and $000000FF)); //Address High byte

WritePortb($81,((Addr shr 16) and $000000FF)); //External Page Register

WritePortb($0C,$FF); //Reset Flip-Flop
WritePortb($05,(Count and $000000FF));         //Count low byte
WritePortb($05,((Count shr 8) and $000000FF)); //Count High byte

WritePortb($0B,Mode); //Set Mode -see above
WritePortb($0A,$02);  //Unmask DMA 2
end;

function FloppyDoTrackLBA(Drive : byte; LBA : byte; dir : byte;
NoSectors : byte) : byte;
var
cmd, i, st0, st1, st2, rcy, rhe, rse, bps, error : byte;
cyl, head, sec : byte;
begin
error := 0;

case dir of
1  : cmd := FloppyCmd[5] or $C0; //Read
2  : cmd := FloppyCmd[4] or $C0; //Write
end;

LBA2CHS(LBA, cyl, head, sec);
Size := NoSectors * 512;

if (Seek(Drive, cyl, head)) = -1 then
  begin
  FloppyDoTrackLBA := -1;
  Exit;
  end;

for i := 1 to 20 do
 begin
   Motor(Drive, 1);
   FloppyDMAInit(dir, Size);

   Delay(100);

   FloppyWriteCmd(Drive, cmd);
   FloppyWriteCmd(Drive, ((head shl 2) or Drive));
   FloppyWriteCmd(Drive, cyl);
   FloppyWriteCmd(Drive, head);
   FloppyWriteCmd(Drive, sec);
   FloppyWriteCmd(Drive, 2);
   FloppyWriteCmd(Drive, 0);
   FloppyWriteCmd(Drive, 0);
   FloppyWriteCmd(Drive, $FF);

   IRQWait(6);

   st0 := FloppyReadCmd(Drive);
   st1 := FloppyReadCmd(Drive);
   st2 := FloppyReadCmd(Drive);

   //Read Cylinder, Head, Sector
   rcy := FloppyReadCmd(Drive);
   rhe := FloppyReadCmd(Drive);
   rse := FloppyReadCmd(Drive);

   bps := FloppyReadCmd(Drive);

   if error = 0  then
    begin
      Motor(Drive, 0);
      FloppyDoTrackLBA := 0;
      Exit;
    end;

   if error >= 1 then
    begin
      
      Motor(Drive, 0);
      FloppyDoTrackLBA := -2;
       asm
         int 24h //trip the handler for critical Disk I/O
      end;
      error:=0;
      FloppyDoTrack:=0;
      Exit;
    end;
 end;

WriteLn(#10'Floppy Read Write Timeout');
Motor(Drive, 0);
FloppyDoTrackLBA := -1;
end;

function FloppyDoTrack(Drive : byte; cyl : byte; dir : byte) : byte;
var
cmd, i, st0, st1, st2, rcy, rhe, rse, bps, error : byte;
begin
error := 0;

case dir of
1  : cmd := FloppyCmd[5] or $C0; //Read
2  : cmd := FloppyCmd[4] or $C0; //Write
end;

Size := DMABufLen;

if (Seek(Drive, cyl, 0)) or (Seek(Drive, cyl, 1)) = -1 then
  begin
  FloppyDoTrack := -1;
  Exit;
  end;

for i := 1 to 20 do
 begin
   Motor(Drive, 1);
   FloppyDMAInit(dir, Size);

   Delay(100);

   FloppyWriteCmd(Drive, cmd);
   FloppyWriteCmd(Drive, 0);
   FloppyWriteCmd(Drive, cyl);
   FloppyWriteCmd(Drive, 0);
   FloppyWriteCmd(Drive, 1);
   FloppyWriteCmd(Drive, 2);
   FloppyWriteCmd(Drive, 18);
   FloppyWriteCmd(Drive, $1B);
   FloppyWriteCmd(Drive, $FF);

   IRQWait(6);

   st0 := FloppyReadCmd(Drive);
   st1 := FloppyReadCmd(Drive);
   st2 := FloppyReadCmd(Drive);

   //Read Cylinder, Head, Sector
   rcy := FloppyReadCmd(Drive);
   rhe := FloppyReadCmd(Drive);
   rse := FloppyReadCmd(Drive);

   bps := FloppyReadCmd(Drive);

   if error = 0  then
    begin
      Motor(Drive, 0);
      FloppyDoTrack := 0;
      Exit;
    end;

   if error >= 1 then
    begin
      Motor(Drive, 0);
      FloppyDoTrack := -2
      asm
         int 24h //trip the handler for critical Disk I/O
      end;
      error:=0;
      FloppyDoTrack:=0;
      Exit;
    end;
 end;

WriteLn(#10'Floppy Read /Write Timeout');
Motor(Drive, 0);
FloppyDoTrack := -1;
end;

function FloppyRead(Drive : byte; Data : byte; LBA : boolean; NoSec :
byte) : byte;
begin
if LBA = false then
  FloppyRead := FloppyDoTrack(Drive, Data, 1);

if LBA = true then
  FloppyRead := FloppyDoTrackLBA(Drive, Data, 1, NoSec);
end;

function FloppyWrite(Drive : byte; Data : byte; LBA : boolean; NoSec :
byte) : byte;
begin
if LBA = false then
  FloppyWrite := FloppyDoTrack(Drive, Data, 2);

if LBA = true then
  FloppyWrite := FloppyDoTrackLBA(Drive, Data, 2, NoSec);
end;

procedure initFloppy;
var
s : string;
b : Byte;
begin
WriteLn(#10'Locating floppy drives...');
DetectDrives;
WriteLn(#10'Installing floppy driver');
FloppyReset(0);
WriteLn(#10'Floppy driver install done');

end;


---------


On Thu, 2009-05-07 at 19:05 -0700, pete.goodeve@xxxxxxxxxxxx wrote:

> On Mon, May 04, 2009 at 01:16:20PM +0200, Ingo Weinhold wrote:
> > 
> > > [...on changing script recognition]  To me, it looks fine, but I have only
> > > a dim grasp of what I'm looking at.
> > 
> > So do I. In r30626 I changed it accordingly anyway. ;-)
> > 
> I got rather sidetracked for a while there, but I can now happily report
> that, with Ingo's fix and the required Haiku directory changes, xicon
> now works a treat!
> 
> Thanks Ingo...!
>                       -- Pete --
> 
> 

Other related posts: