unit MainUnit; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TCOSData = array of packed record A, B, C: Byte; end; TMainForm = class(TForm) LogMemo: TMemo; Panel2: TPanel; CardCombo: TComboBox; ControlPanel: TPanel; WDGGroup: TGroupBox; WDGIRQButton: TButton; SoftRestartRadio: TRadioButton; MostlySoftRestartRadio: TRadioButton; DisableWDGCheck: TCheckBox; NoRestartRadio: TRadioButton; GoWDGButton: TButton; CancelWDGButton: TButton; TempButton: TButton; StatusButton: TButton; RebootButton: TButton; COSGroup: TGroupBox; COSDataLabel: TLabel; COSIRQButton: TButton; GenGroup: TGroupBox; GenIRQLabel: TLabel; GenIRQButton: TButton; AbortButton: TButton; StatusLabel: TLabel; TempLabel: TLabel; WDGTime: TTimer; procedure GenIRQButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure AbortButtonClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure COSIRQButtonClick(Sender: TObject); procedure WDGIRQButtonClick(Sender: TObject); procedure GoWDGButtonClick(Sender: TObject); procedure CancelWDGButtonClick(Sender: TObject); procedure TempButtonClick(Sender: TObject); procedure StatusButtonClick(Sender: TObject); procedure RebootButtonClick(Sender: TObject); procedure CardComboChange(Sender: TObject); procedure WDGPetTimer(Sender: TObject); procedure WDGWaitTimer(Sender: TObject); private procedure CtrLoad(addr, c, val: word); procedure CtrMode(addr: word; cntr, mode: byte); public procedure AddLine(CardNum: Integer; Line: String); procedure ReceiveGenIRQ(CardNum: Integer); procedure ReceiveCOSData(CardNum: Integer; COSData: TCOSData); end; var MainForm: TMainForm; implementation {$R *.DFM} uses IRQThreadUnit, AIOWDM; type TCardData = record Base: LongWord; PPIs: LongWord; IsWDG: Boolean; IRQCount: LongWord; LastCOSData: TCOSData; Log: String; WDGPets: LongWord; end; var CardData: array of TCardData; procedure TMainForm.FormCreate(Sender: TObject); var NumCards, CardNum, I, J: Integer; DeviceID, Base: LongWord; NameSize: LongWord; Name: String; Success: LongWord; begin CardCombo.Items.Clear; NumCards := GetNumCards; if NumCards = 0 then begin GenGroup.Visible := False; COSGroup.Visible := False; WDGGroup.Visible := False; if (InPortB($61) = $AA55) then begin Application.MessageBox('ACCESNT.SYS not detected. Please copy ACCESNT.SYS into [NT]/system32/drivers and re-run this sample.', 'Warning', IDOK); end; for I := 0 to ControlPanel.ControlCount - 1 do for J := 0 to TWinControl(ControlPanel.Controls[I]).ControlCount - 1 do TWinControl(ControlPanel.Controls[I]).Controls[J].Enabled := False ; LogMemo.Text := 'No cards found. The cards may not be installed, or they may be installed using a driver other than AIOWDM.sys.'; end else begin SetLength(CardData, NumCards); for CardNum := 0 to NumCards - 1 do begin NameSize := 256; SetString(Name, nil, NameSize); Success := QueryCardInfo(CardNum, @DeviceID, @Base, @NameSize, PChar(Name)); SetLength(Name, NameSize - 1); if Success = 0 then CardCombo.Items.Add('Error getting data: ' + Name + '[' + IntToHex(Base, 3) + ']') else begin CardCombo.Items.Add(Name + '[' + IntToHex(Base, 3) + ']'); CardData[CardNum].Base := Base; case DeviceID of $0E50, $ACA8: begin //PCI-DIO-24S CardData[CardNum].PPIs := 1; SetLength(CardData[CardNum].LastCOSData, CardData[CardNum].PPIs); end; $0E60: begin //PCI-DIO-48S CardData[CardNum].PPIs := 2; SetLength(CardData[CardNum].LastCOSData, CardData[CardNum].PPIs); end; $22C0, $25C0, $2FC0, $2FC1: begin //PCI-WDG-CSM, P104-WDG-E, P104-WDG-CSM, and P104-WDG-CSMA CardData[CardNum].IsWDG := True; WDGInit(CardNum); end; end; if CardData[CardNum].PPIs <> 0 then CardData[CardNum].Log := 'AIOWDM provides generic IRQ-handling functions for all cards ' + 'and special IRQ-handling functions for COS cards like this one.'#13#10#13#10 + 'Click "Detect Generic IRQs" to handle IRQs generically for the card selected above, ' + 'or "Detect COS IRQs" to handle IRQs for the card selected above by updating COS data.'#13#10#13#10 else if CardData[CardNum].IsWDG then CardData[CardNum].Log := 'AIOWDM provides generic IRQ-handling functions for all cards ' + 'and special functions for watchdog cards like this one.'#13#10#13#10 + 'Click "Detect Generic IRQs" to handle IRQs generically for the card selected above, ' + 'or "Handle Watchdog IRQ" to handle the next IRQ for the card selected above with the selected action.'#13#10#13#10 + 'You can also click "Test Watchdog Timing" to set the watchdog timer, pet it a few times, then let it time out, ' + '"Read Temp" to read the temperature(if installed), ' + '"Read Status" to read the card''s status byte, ' + 'or "Reboot" to quickly reboot your computer.'#13#10#13#10 else CardData[CardNum].Log := 'AIOWDM provides generic IRQ-handling functions for all cards.'#13#10#13#10 + 'Click "Detect Generic IRQs" to handle IRQs for the card selected above.'#13#10#13#10 ; end; end; CardCombo.ItemIndex := 0; CardComboChange(CardCombo); end; end; procedure TMainForm.CardComboChange(Sender: TObject); var CardNum: Integer; Buf: String; I: Integer; begin CardNum := CardCombo.ItemIndex; LogMemo.Text := CardData[CardNum].Log; LogMemo.SelStart := Length(CardData[CardNum].Log); LogMemo.SelLength := 1; //Generic IRQs if CardData[CardNum].IRQCount = 0 then GenIRQLabel.Caption := '' else GenIRQLabel.Caption := IntToStr(CardData[CardNum].IRQCount) + ' IRQ(s) detected' ; //COS IRQs if CardData[CardNum].PPIs <> 0 then begin Buf := ''; for I := 0 to High(CardData[CardNum].LastCOSData) do Buf := Buf + ' ' + IntToHex(CardData[CardNum].LastCOSData[I].A, 2) + ' ' + IntToHex(CardData[CardNum].LastCOSData[I].B, 2) + ' ' + IntToHex(CardData[CardNum].LastCOSData[I].C, 2) ; COSDataLabel.Caption := Buf; COSGroup.Visible := True; outportb(CardData[CardNum].Base+11,$00); end else COSGroup.Visible := False //Hide COS IRQ stuff if it's not a COS card ; //Hide watchdog stuff if it's not a watchdog card WDGGroup.Visible := CardData[CardNum].IsWDG; TempLabel.Caption := ''; StatusLabel.Caption := ''; end; procedure TMainForm.GenIRQButtonClick(Sender: TObject); var CardNum: Integer; Thrd: TIRQThread; begin CardNum := CardCombo.ItemIndex; Thrd := TIRQThread.Create(True); Thrd.COSPPIs := 0; Thrd.CardNum := CardNum; Thrd.Resume; AddLine(CardNum, 'Detecting generic IRQs; generate IRQs to see this sample count them. Press "Abort IRQ Detect" to cancel when done.'); end; procedure TMainForm.COSIRQButtonClick(Sender: TObject); var Thrd: TIRQThread; CardNum: Integer; begin CardNum := CardCombo.ItemIndex; Thrd := TIRQThread.Create(True); Thrd.CardNum := CardNum; Thrd.COSPPIs := CardData[CardNum].PPIs; Thrd.Resume; AddLine(CardNum, 'Detecting COS IRQs; change the input data to see the COS data update. Press "Abort IRQ Detect" to cancel when done.'); end; procedure TMainForm.AbortButtonClick(Sender: TObject); var CardNum: Integer; begin CardNum := CardCombo.ItemIndex; if AbortRequest(CardNum) <> 0 then AddLine(CardNum, 'Aborting IRQ detection...') else AddLine(CardNum, 'No IRQ request to abort.') ; end; procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var CardNum: Integer; begin { Abort all pending IRQ requests. If we don't do this before exiting, later when an IRQ comes in or somebody else calls AbortRequest the pending IRQ request will attempt to unlock a thread that no longer exists, which is bad. (We can AbortRequest for a card with no pending requests, it'll just tell us that, and it's easier than remembering which cards have pending requests.) } for CardNum := 0 to GetNumCards - 1 do AbortRequest(CardNum) ; end; procedure TMainForm.WDGIRQButtonClick(Sender: TObject); var Action: LongWord; CardNum: Integer; begin CardNum := CardCombo.ItemIndex; if SoftRestartRadio.Checked then Action := WDG_ACTION_SOFT_RESTART else if MostlySoftRestartRadio.Checked then Action := WDG_ACTION_MOSTLY_SOFT_RESTART else Action := WDG_ACTION_IGNORE ; if DisableWDGCheck.Checked then Action := Action + WDG_ACTION_DISABLE ; WDGHandleIRQ(CardNum, Action); AddLine(CardNum, 'Watchdog IRQ handler started, press "Abort IRQ Detect" to cancel.'); end; procedure TMainForm.GoWDGButtonClick(Sender: TObject); var CardNum: Integer; begin CardNum := CardCombo.ItemIndex; WDGSetTimeout(CardNum, 2 * 1000, PCI_WDG_CSM_RATE); //2 sec timeout WDGSetResetDuration(CardNum, 1, PCI_WDG_CSM_RATE); //infinite reset //WDGSetResetDuration(CardNum, 250, PCI_WDG_CSM_RATE); //250 ms reset WDGStart(CardNum); AddLine(CardNum, 'Watchdog timing started...'); CardData[CardNum].WDGPets := 0; WDGTime.Tag := CardNum; WDGTime.OnTimer := WDGPetTimer; WDGTime.Interval := 1000; WDGTime.Enabled := True; end; procedure TMainForm.WDGPetTimer(Sender: TObject); var CardNum: Integer; begin CardNum := WDGTime.Tag; if (InPortB(CardData[CardNum].Base + 4) and $01) = 0 then begin AddLine(CardNum, 'Watchdog timed out early!'); WDGTime.Enabled := False; Exit; end; Inc(CardData[CardNum].WDGPets); if CardData[CardNum].WDGPets >= 4 then begin AddLine(CardNum, 'Waiting for timeout...'); WDGTime.OnTimer := WDGWaitTimer; WDGTime.Interval := 100; end else begin WDGPet(CardNum); AddLine(CardNum, 'Petting watchdog, pet ' + IntToStr(CardData[CardNum].WDGPets) + ' of 3...'); end; end; procedure TMainForm.WDGWaitTimer(Sender: TObject); begin if (InPortB(CardData[WDGTime.Tag].Base + 4) and $01) = 0 then begin AddLine(WDGTime.Tag, 'Watchdog timed out.'); WDGTime.Enabled := False; end; end; procedure TMainForm.CancelWDGButtonClick(Sender: TObject); var CardNum: Integer; begin CardNum := CardCombo.ItemIndex; WDGStop(CardNum); WDGTime.Enabled := False; AddLine(CardNum, 'Watchdog timing cancelled.'); end; procedure TMainForm.TempButtonClick(Sender: TObject); begin TempLabel.Caption := FloatToStr(WDGReadTemp(CardCombo.ItemIndex)); end; procedure TMainForm.StatusButtonClick(Sender: TObject); begin StatusLabel.Caption := IntToHex(WDGReadStatus(CardCombo.ItemIndex), 2); end; procedure TMainForm.RebootButtonClick(Sender: TObject); begin if EmergencyReboot <> 0 then AddLine(CardCombo.ItemIndex, 'Rebooting...') else AddLine(CardCombo.ItemIndex, 'Reboot failed.') ; end; procedure TMainForm.AddLine(CardNum: Integer; Line: String); begin CardData[CardNum].Log := CardData[CardNum].Log + Line + #13#10#13#10; if CardNum = CardCombo.ItemIndex then CardComboChange(CardCombo); end; procedure TMainForm.ReceiveCOSData(CardNum: Integer; COSData: TCOSData); begin CardData[CardNum].LastCOSData := COSData; if CardNum = CardCombo.ItemIndex then CardComboChange(CardCombo); end; procedure TMainForm.ReceiveGenIRQ(CardNum: Integer); begin Inc(CardData[CardNum].IRQCount); if CardNum = CardCombo.ItemIndex then CardComboChange(CardCombo); end; //--------------------------------------------------------------------------- procedure TMainForm.CtrMode(addr: word; cntr, mode: byte); begin OutPortB(addr+3, (cntr shl 6) or $30 or (mode shl 1)); end; procedure TMainForm.CtrLoad(addr: word; c, val: word); begin OutPortB(addr+c, val and $00FF); OutPortB(addr+c, (val shr 8) and $00FF); end; end.