head     56.4;
access   paws bayes jws quist dew jwh;
symbols  ;
locks    ; strict;
comment  @# @;


56.4
date     93.01.27.13.53.57;  author jwh;  state Exp;
branches ;
next     56.3;

56.3
date     93.01.27.12.26.02;  author jwh;  state Exp;
branches ;
next     56.2;

56.2
date     92.05.26.17.07.15;  author cfb;  state Exp;
branches ;
next     56.1;

56.1
date     91.11.05.10.01.40;  author jwh;  state Exp;
branches ;
next     55.2;

55.2
date     91.08.27.15.00.37;  author cfb;  state Exp;
branches ;
next     55.1;

55.1
date     91.08.25.10.36.30;  author jwh;  state Exp;
branches ;
next     54.1;

54.1
date     91.03.18.15.37.09;  author jwh;  state Exp;
branches ;
next     53.1;

53.1
date     91.03.11.19.35.43;  author jwh;  state Exp;
branches ;
next     52.1;

52.1
date     91.02.19.09.21.49;  author jwh;  state Exp;
branches ;
next     51.1;

51.1
date     91.01.30.16.20.26;  author jwh;  state Exp;
branches ;
next     50.1;

50.1
date     90.10.29.16.34.18;  author jwh;  state Exp;
branches ;
next     49.1;

49.1
date     90.08.14.14.17.56;  author jwh;  state Exp;
branches ;
next     48.1;

48.1
date     90.07.26.11.24.32;  author jwh;  state Exp;
branches ;
next     47.1;

47.1
date     90.05.14.11.11.03;  author dew;  state Exp;
branches ;
next     46.1;

46.1
date     90.05.07.08.58.09;  author jwh;  state Exp;
branches ;
next     45.1;

45.1
date     90.04.19.16.06.00;  author jwh;  state Exp;
branches ;
next     44.1;

44.1
date     90.04.01.22.25.30;  author jwh;  state Exp;
branches ;
next     43.1;

43.1
date     90.03.20.14.15.55;  author jwh;  state Exp;
branches ;
next     42.2;

42.2
date     90.03.13.15.41.47;  author dew;  state Exp;
branches ;
next     42.1;

42.1
date     90.01.23.17.59.57;  author jwh;  state Exp;
branches ;
next     41.3;

41.3
date     90.01.18.23.03.10;  author dew;  state Exp;
branches ;
next     41.2;

41.2
date     90.01.10.15.10.49;  author dew;  state Exp;
branches ;
next     41.1;

41.1
date     89.12.22.11.41.40;  author jwh;  state Exp;
branches ;
next     40.6;

40.6
date     89.11.29.10.29.06;  author dew;  state Exp;
branches ;
next     40.5;

40.5
date     89.11.10.19.33.16;  author dew;  state Exp;
branches ;
next     40.4;

40.4
date     89.10.24.13.22.31;  author dew;  state Exp;
branches ;
next     40.3;

40.3
date     89.10.18.17.04.08;  author dew;  state Exp;
branches ;
next     40.2;

40.2
date     89.10.11.17.02.17;  author dew;  state Exp;
branches ;
next     40.1;

40.1
date     89.09.29.12.02.47;  author jwh;  state Exp;
branches ;
next     39.1;

39.1
date     89.09.26.16.47.39;  author dew;  state Exp;
branches ;
next     1.1;

1.1
date     89.09.14.10.24.08;  author dew;  state Exp;
branches ;
next     ;


desc
@OSD_LL is the PWS Operating System Dependent, Low Level, module that
ties the SCSI Generic Driver into PWS.
@


56.4
log
@
pws2rcs automatic delta on Wed Jan 27 13:14:25 MST 1993
@
text
@{
	This module interfaces the scsi driver to the lowest parts of an O/S.

	This module is responsible for allowing access to the SelectCodeBlock,
	allowing one to read and set interrupt levels, interfacing the interrupt level
	routine to the o/s's interrupt handling mechanism, etc.
}



MODULE OSD_LL; {Operating System Dependent Low Level interface}

import SCSI_DEFS, OSD_LLA, IODECLARATIONS, GENERAL_0, SYSGLOBALS, ISR, ASM, IOCOMASM;

export

const
	one_second    = 1000;

	{
	  Driver Initialization routines
	}
	Procedure osdInitScBlock(Sc:S_TYPE_ISC);
	Function  osdGetScBlock(Sc:S_TYPE_ISC):PtrSelectCodeBlockType;
	Procedure osdLinkIsrRoutine(IsrProc:ScsiIsrProcType; Sc:S_TYPE_ISC);

	{
	  Timer Routines
	}
	Procedure osdDelay(ms:integer);
	Procedure osdStartTimer(ms:integer);
	Function  osdTimeExpired:boolean;

	{
	  General O/S specific routines
	}
	Function  osdGetRunLevel:io_byte;
	Procedure osdSetRunLevel(Level:io_byte);
	Function  osdBitOr(b1,b2:integer):integer;
	Function  osdBitAnd(b1,b2:integer):integer;
	Function  osdBitLsL(b,Num:integer):integer;
	Function  osdBitLsR(b,Num:integer):integer;

	{
	  DMA routines
	}
	Function  osdDMA32bit:boolean;
	Function  osdGetDMAChannel(Sc:S_TYPE_ISC):integer;
	Procedure osdSetUpDMAChannel(Channel:integer; var DMA32bit:boolean; var XferBlock:XferBlockType);
	Procedure osdKillDMA(Channel:integer);
	Function  osdStopDMA(Channel:integer; DMA32bit:boolean; StopCount:integer):boolean;
	Procedure osdReleaseDMAChannel(Sc:S_TYPE_ISC);

implement

{
  define record structures for the DMA registers
}
type
	Channel16BitType = packed record
		address:ANYPTR;
		count:S_SHORT;
		cont_stat:S_SHORT;
	end;

	Channel32BitType = packed record
		address:ANYPTR;
		count:integer;
		cont_stat:S_SHORT;
	end;

	Channel32BitGeneralType = packed record
		id1:S_SHORT;
		id2:S_SHORT;
		case integer of
		1:(control:S_SHORT);
		2:(pad    :0..hex('3ff');
		   reset1 :boolean;
		   reset0 :boolean;
		   bt     :0..hex('3');
		   br     :0..hex('3'));
	end;

var
	timer:timer_rec;




{*************************************************************************
 *  osdInitScBlock
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Acquire memory for a Select Code Block (defined in SCSI_DEFS),
 *      hook the memory into a memory chain accessible through a select
 *      code, and initialize.
 *
 * On Output:  SelectCode block acquired, hooked into the O/S and initialized.
 *
 *************************************************************************}
Procedure osdInitScBlock(Sc:S_TYPE_ISC);
type
	MiscTemplate = packed record
		MiscpScBlock:PtrSelectCodeBlockType;
		MiscpSenseSpace:PtrChar;
		MiscSenseLength:integer;
	end;
	PtrMiscTemplateType = ^MiscTemplate;
var
	PtrMiscTemplate:PtrMiscTemplateType;
	i:ScsiDeviceType;
begin
	with isc_table[Sc]  do
	begin
		PtrMiscTemplate := addr(io_tmp_ptr^.drv_misc[1]);
		with PtrMiscTemplate^ do
		begin
			newbytes(MiscpScBlock, sizeof(SelectCodeBlockType));
			with MiscpScBlock^ do
			begin
				for i := 0 to 7 do
				begin
					DeviceSessionPtrs[i] := nil;
					DeviceSynchParms[i].SynchState := NoSynch;
					DeviceSynchParms[i].TMODvalue.tmod := 0;
				end;
				PtrScsiCard := card_ptr;
				PtrScsiChip := addr(PtrChar(PtrScsiCard)^,32);
				ScsiIntLevel := PtrScsiCard^.sc_reg.intlevel+3;
				ScsiSelectCode := Sc;
				DMAInProgress := FALSE;
				DMAChannel := -1;
			end;
			newbytes(MiscpSenseSpace, 256);
			MiscSenseLength := 0;
		end;
	end;
end;

{*************************************************************************
 *  osdGetScBlock
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Given a select code, return a pointer to the SelectCode block.
 *
 * On Output:  Ptr to SelectCodeBlock or Nil.
 *
 *************************************************************************}
Function osdGetScBlock(Sc:S_TYPE_ISC):PtrSelectCodeBlockType;
type
	ppScBlock = ^PtrSelectCodeBlockType;
begin
	with isc_table[Sc] do
	begin
		if (card_type = scsi_card) then
			osdGetScBlock := ppScBlock(addr(io_tmp_ptr^.drv_misc[1]))^
		else
			osdGetScBlock := Nil;
	end;
end;


{*************************************************************************
 *  osdLinkIsrRoutine
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Takes as paramters a select code and an ISR routine.  The ISR
 *      routine is linked into the O/S for the given Select Code.
 *
 *      The ISR routine address can be stored off of the SelectCodeBlock.
 *
 *      PWS implmentation:  Use a procedure that can recieve an ISRIB.
 *              From this get the select code, get the SelectCodeBlock,
 *              get and call the SCSI Driver ISR routine.
 *
 * On Output:  SCSI Driver ISR routine is linked into the O/S.
 *
 *************************************************************************}
Procedure osdScsiIsr(isribptr:pisrib);
var
	io_ptr:pio_tmp_ptr;
	pScBlock:PtrSelectCodeBlockType;
begin
	io_ptr := pio_tmp_ptr(isribptr);
	pScBlock := osdGetScBlock(io_ptr^.my_isc);
	call(pScBlock^.ScsiIsrProc, io_ptr^.my_isc);
end;

Procedure osdLinkIsrRoutine(IsrProc:ScsiIsrProcType; Sc:S_TYPE_ISC);
var
	pScBlock:PtrSelectCodeBlockType;
	pCard:PtrScsiCardType;
	p:ANYPTR;
begin
	pScBlock := osdGetScBlock(Sc);
	with isc_table[Sc], io_tmp_ptr^, pScBlock^, pScBlock^.PtrScsiCard^ do
	begin
		{
		  Check for ISR already in place.
		}
		if myisrib.intregaddr <> nil then  {isr already exits}
		begin
			{
			  unlink existing isr hook.
			}
			isrunlink(ScsiIntLevel, addr(myisrib));
		end;

		ScsiIsrProc := IsrProc;
		p := addr(sc_reg,1); {sc_reg.status, compiler won't let me otherwise}
		permisrlink(osdScsiIsr, p, hex('c0'), hex('c0'), ScsiIntLevel,
			addr(myisrib));
	end;
end;


{*************************************************************************
 *  osdDelay
 *************************************************************************
 *
 * On Input: Nothing is expected.
 *
 *
 * Functional Description:
 *
 *      Delay the given number of milliseconds.
 *
 * On Output:  Nothing is changed, however the given number of milliseconds
 *      has passed.
 *
 *************************************************************************}
Procedure osdDelay(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
	repeat until time_expired(timer);
end;


{*************************************************************************
 *  osdStartTimer & osdTimeExpired
 *************************************************************************
 *
 * On Input: Nothing is expected.
 *
 *
 * Functional Description:
 *
 *      These two routines are used to start a timer that will expire after
 *      a given number of milliseconds and then check to see if the timer
 *      has expired.
 *
 *      They are used to wait while waiting for an event to happen, thus
 *      preventing an eternal wait.
 *
 * On Output:  osdStartTimer: the timer has been started - this should not
 *      affect the driver in any way.  osdTimeExpired: returns TRUE if the
 *      timer has expired, FALSE otherwise.  This routine should have no
 *      affect on the driver.
 *
 *************************************************************************}
Procedure osdStartTimer(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
end;

Function osdTimeExpired:boolean;
begin
	osdTimeExpired := time_expired(timer);
end;



{*************************************************************************
 *  osdGetRunLevel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Returns the current run level of the 680x0 processor.
 *
 * On Output:
 *
 *
 *************************************************************************}
Function osdGetRunLevel:io_byte;
begin
	osdGetRunLevel := intlevel;
end;


{*************************************************************************
 *  osdSetRunLevel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Sets the current run level of the 680x0 processor to the requested
 *      level.
 *
 * On Output:  680x0 run level is at requested level.
 *
 *************************************************************************}
Procedure osdSetRunLevel(Level:io_byte);
begin
	setintlevel(level);
end;



{*************************************************************************
 *  Bit manipulation routintes
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *
 *
 * On Output:
 *
 *
 *************************************************************************}
Function osdBitOr(b1,b2:integer):integer;
begin
	osdBitOr := binior(b1,b2);
end;
Function osdBitAnd(b1,b2:integer):integer;
begin
	osdBitAnd := binand(b1,b2);
end;
Function osdBitLsL(b,Num:integer):integer;
begin
	osdBitLsL := binlsl(b,Num);
end;
Function osdBitLsR(b,Num:integer):integer;
begin
	 osdBitLsR := binlsr(b,Num);
end;


{*************************************************************************
 *  osdDMA32bit
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Determines if the current hardware supports 32 bit wide DMA.
 *
 * On Output:  TRUE if 32bit wide DMA is supported; FALSE otherwise.
 *             Modified to always FALSE due to hardware bug - 27AUG91 - CFB
 *
 *************************************************************************}
Function osdDMA32bit:boolean;
var
	io_dummy_word:io_word;
begin
	if dma_here then {from IODECLARATIONS}
	begin
		try
			io_dummy_word := ioread_word(3, hex('10'));
			if (io_dummy_word = hex('3230')) then  {ascii'2', '0'}
				osdDMA32bit := true
			else
				osdDMA32bit := false;
		recover
			osdDMA32bit := false;
	end
	else
		osdDMA32bit := false;
	osdDMA32bit := false; {always false due to hardware bug 27AUG91 - CFB}
end;


{*************************************************************************
 *  osdGetDMAChannel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Acquire, if possible, a DMA Channel from the operating system.
 *      Once acquired, this channel will be used by the SCSI Driver until
 *      the SCSI driver releases it.
 *
 * On Output:  0 for channel 0, 1 for channel 1, -1 for no channel.
 *
 *
 *************************************************************************}
Function osdGetDMAChannel(Sc:S_TYPE_ISC):integer;
begin
	osdGetDMAChannel := dma_request(isc_table[Sc].io_tmp_ptr);
end;


{*************************************************************************
 *  osdSetUpDMAChannel
 *************************************************************************
 *
 * On Input: DMA is present, and a Channel has been acquired.
 *           XferBlock.BufPtr is guaranteed to be on a word boundary and
 *           XferBlock.BufLen is guaranteed to be an even length.
 *
 * Functional Description:
 *
 *      Initialize and ARM the given DMA channel.  The DMA H/W should
 *      be set up to NOT interrupt.
 *
 *      The incomming
 *      DMA32bit parameter indicates if the SCSI H/W can handle 32 bit DMA or
 *      not, on exit DMA32bit should indicate if 32 bit DMA is being performed
 *      or not. (NOTE: SCSI driver expects either 16 or 32 bit DMA - 8 bit DMA
 *      is NOT acceptable).
 *
 *      XferBlock contains buffer address, length, and direction of transfer.
 *
 *      Because 16bit DMA can only transfer 128K max, the amount of data being
 *      transfered should be stored in the XferBlock (XferDMACount).  The value
 *      stored is the actual number of bytes the DMA channel will transfer.
 *
 * On Output:  DMA channel is initialized and ARMed.
 *
 *************************************************************************}
Procedure osdSetUpDMAChannel(Channel:integer; var DMA32bit:boolean; var XferBlock:XferBlockType);
var
	DMAPtr:PtrChar;
	Use32BitChannel:boolean;
	pChannel16:^Channel16BitType;
	pChannel32:^Channel32BitType;
	p32Gen:^Channel32BitGeneralType;
	i:integer;
begin
	{
	  Determine if a 16 or 32 bit channel should be used.
	}
	Use32BitChannel := osdDMA32bit;

	{
	  Determine what kind of DMA should be used, 16 or 32 bit.
	}
	if (DMA32bit) then
	begin
		DMA32bit := false;  {prove that SPU can do 32 bit first.}

		{is 32 bit wide DMA available in the SPU?}
		if (Use32BitChannel) then
		begin
			{is the buffer on a long word boundary?}
			i := integer(XferBlock.XferBufBlock.BufPtr);
			if (i mod 4) = 0 then
			begin
				{is the length divisible by 4?}
				i := XferBlock.XferBufBlock.BufLen;
				if (i mod 4) = 0 then
					DMA32bit := TRUE;
			end;
		end;
	end;

	osdKillDMA(Channel);

	DMAPtr := isc_table[3].card_ptr;
	if Use32BitChannel then
	begin
		{Get pointers to DMA channel}
		p32Gen     := addr(DMAPtr^,hex('10'));
		pChannel32 := addr(DMAPtr^,(Channel+1)*hex('100'));

		with p32Gen^, pChannel32^, XferBlock do
		begin
			{set bus control registers to 16 bit defaults}
			br := 0;
			bt := 2;

			{DMA address}
			address := XferBufBlock.BufPtr;

			{
			  DMA Count.
			  Can do the entire DMA in one go around, however the amount of transfers
			  depends on the width of the transfer.
			}
			XferDMACount := XferBufBlock.BufLen;
			if (DMA32bit) then
				count := (XferBufBlock.BufLen Div 4)-1
			else
				count := (XferBufBlock.BufLen Div 2)-1;

			{
			  Writing the start bit in the control register arms the DMA chip.
			}
			if (XferBlock.XferPhase = data_in_phase) then
			begin
				if DMA32bit then
					{start, 32bit, priority, input, word, no interrupt}
					cont_stat := hex('810A')
				else
					{start, 16bit, priority, input, word, no interrupt}
					cont_stat := hex ('800A');
			end
			else
			begin
				if DMA32bit then
					{start, 32bit, priority, output, word, no interrupt}
					cont_stat := hex('810E')
				else
					{start, 16bit, priority, output, word, no interrupt}
					cont_stat := hex('800E');
			end;
		end;
	end
	else
	begin
		{Get pointer to DMA channel}
		pChannel16 := addr(DMAPtr^, Channel*8);

		with pChannel16^, XferBlock do
		begin
			{DMA address}
			address := XferBufBlock.BufPtr;

			{DMA count (in words). DMA count is 1 less than total request. 128K transfer MAX.}
			if XferBufBlock.BufLen >= hex('20000') then {len >= 128K}
			begin
				XferDMACount := hex('20000');
				i := hex('ffff');
			end
			else
			begin
				XferDMACount := XferBufBlock.BufLen;
				i := (XferBufBlock.BufLen Div 2)-1;
			end;

			count := i;

			{
			  Writing the control register arms the DMA chip.
			}
			if (XferBlock.XferPhase = data_in_phase) then
				cont_stat := hex('000A')  {priority, input, word, no interrupt}
			else
				cont_stat := hex('000E'); {priority, output, word, no interrupt}
		end;
	end;
end;

{*************************************************************************
 *  osdKillDMA
 *************************************************************************
 *
 * On Input: DMA channel is actively transfering data.
 *
 *
 * Functional Description:
 *
 *      shutdown active DMA Channel.
 *      Force all data (instruction and data) in the processor's cache
 *      to be flushed.
 *
 * On Output:  active DMA channel is shutdown.
 *
 *
 *************************************************************************}
Procedure osdKillDMA(Channel:integer);
var
	io_dummy_word:io_word;
	pGen32:^Channel32bitGeneralType;
begin
	{
	  Kill the 16 bit channel by reading the channel address register.
	}
	io_dummy_word := ioread_word(3, Channel*8);

	{
	  Kill the 32 bit channel by specifically resetting the
	  appropriate channel.
	}
	pGen32 := isc_table[3].card_ptr;
	pGen32 := addr(pGen32^, hex('10'));
	if Channel = 0 then
		pGen32^.reset0 := true
	else
		pGen32^.reset1 := true;

	{
	  Flush the cache on 68020 and newer processors.
	   - this happens automatically with dma_release.
	}
end;


{*************************************************************************
 *  osdStopDMA
 *************************************************************************
 *
 * On Input: DMA channel is actively transfering data.
 *
 *
 * Functional Description:
 *
 *      Wait for the DMA channel to get to the desired count, and then kill it.
 *      (After an appropriate wait, kill the channel even if the desired count
 *       hasn't been reached).
 *
 * On Output:  TRUE: desired count reached and channel killed.
 *            FALSE: desired count NOT reached, channel killed.
 *
 *
 *************************************************************************}
Function osdStopDMA(Channel:integer; DMA32bit:boolean; StopCount:integer):boolean;
var
	DMAPtr:PtrChar;
	Use32BitChannel:boolean;
	pChannel32:^Channel32BitType;
	Count32:integer;
	pChannel16:^Channel16BitType;
	Count16:S_SHORT;
begin
	Use32BitChannel := osdDMA32bit;
	osdStopDMA := true;
	DMAPtr := isc_table[3].card_ptr;
	if Use32BitChannel then
	begin
		{Get pointer to 32 bit DMA channel}
		pChannel32 := addr(DMAPtr^,(Channel+1)*hex('100'));
		with pChannel32^ do
		begin
			if DMA32bit then
				Count32 := (StopCount Div 4) - 1
			else
				Count32 := (StopCount Div 2) - 1;

			if (count <> Count32) then
			begin
				{wait}
				osdStartTimer(one_second);
				repeat
				until (count <= Count32) or (osdTimeExpired);
				if (count <> Count32) then
					osdStopDMA := false;
			end;
		end;
	end
	else
	begin
		{Get pointer to DMA channel}
		pChannel16 := addr(DMAPtr^, Channel*8);
		with pChannel16^ do
		begin
			Count16 := ((StopCount Div 2) - 1) MOD hex('10000');

			if (count <> Count16) then
			begin
				{wait}
				osdStartTimer(one_second);
				repeat
				until (count <= Count16) or (osdTimeExpired);
				if (count <> Count16) then
					osdStopDMA := false;
			end;
		end;
	end;
	osdKillDMA(Channel);
end;


{*************************************************************************
 *  osdReleaseDMAChannel
 *************************************************************************
 *
 * On Input: Channel is NOT active.
 *
 *
 * Functional Description:
 *
 *      Give the channel back to the O/S.
 *
 * On Output:
 *
 *
 *************************************************************************}
Procedure osdReleaseDMAChannel(Sc:S_TYPE_ISC);
begin
	{release a DMA channel}
	dma_release(isc_table[Sc].io_tmp_ptr);
end;

end;
@


56.3
log
@
pws2rcs automatic delta on Wed Jan 27 11:57:27 MST 1993
@
text
@d1 717
@


56.2
log
@Changed state from NeedSynch to NoSynch to fix bug with 400MB drives - CFB
@
text
@a0 717
{
	This module interfaces the scsi driver to the lowest parts of an O/S.

	This module is responsible for allowing access to the SelectCodeBlock,
	allowing one to read and set interrupt levels, interfacing the interrupt level
	routine to the o/s's interrupt handling mechanism, etc.
}



MODULE OSD_LL; {Operating System Dependent Low Level interface}

import SCSI_DEFS, OSD_LLA, IODECLARATIONS, GENERAL_0, SYSGLOBALS, ISR, ASM, IOCOMASM;

export

const
	one_second    = 1000;

	{
	  Driver Initialization routines
	}
	Procedure osdInitScBlock(Sc:S_TYPE_ISC);
	Function  osdGetScBlock(Sc:S_TYPE_ISC):PtrSelectCodeBlockType;
	Procedure osdLinkIsrRoutine(IsrProc:ScsiIsrProcType; Sc:S_TYPE_ISC);

	{
	  Timer Routines
	}
	Procedure osdDelay(ms:integer);
	Procedure osdStartTimer(ms:integer);
	Function  osdTimeExpired:boolean;

	{
	  General O/S specific routines
	}
	Function  osdGetRunLevel:io_byte;
	Procedure osdSetRunLevel(Level:io_byte);
	Function  osdBitOr(b1,b2:integer):integer;
	Function  osdBitAnd(b1,b2:integer):integer;
	Function  osdBitLsL(b,Num:integer):integer;
	Function  osdBitLsR(b,Num:integer):integer;

	{
	  DMA routines
	}
	Function  osdDMA32bit:boolean;
	Function  osdGetDMAChannel(Sc:S_TYPE_ISC):integer;
	Procedure osdSetUpDMAChannel(Channel:integer; var DMA32bit:boolean; var XferBlock:XferBlockType);
	Procedure osdKillDMA(Channel:integer);
	Function  osdStopDMA(Channel:integer; DMA32bit:boolean; StopCount:integer):boolean;
	Procedure osdReleaseDMAChannel(Sc:S_TYPE_ISC);

implement

{
  define record structures for the DMA registers
}
type
	Channel16BitType = packed record
		address:ANYPTR;
		count:S_SHORT;
		cont_stat:S_SHORT;
	end;

	Channel32BitType = packed record
		address:ANYPTR;
		count:integer;
		cont_stat:S_SHORT;
	end;

	Channel32BitGeneralType = packed record
		id1:S_SHORT;
		id2:S_SHORT;
		case integer of
		1:(control:S_SHORT);
		2:(pad    :0..hex('3ff');
		   reset1 :boolean;
		   reset0 :boolean;
		   bt     :0..hex('3');
		   br     :0..hex('3'));
	end;

var
	timer:timer_rec;




{*************************************************************************
 *  osdInitScBlock
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Acquire memory for a Select Code Block (defined in SCSI_DEFS),
 *      hook the memory into a memory chain accessible through a select
 *      code, and initialize.
 *
 * On Output:  SelectCode block acquired, hooked into the O/S and initialized.
 *
 *************************************************************************}
Procedure osdInitScBlock(Sc:S_TYPE_ISC);
type
	MiscTemplate = packed record
		MiscpScBlock:PtrSelectCodeBlockType;
		MiscpSenseSpace:PtrChar;
		MiscSenseLength:integer;
	end;
	PtrMiscTemplateType = ^MiscTemplate;
var
	PtrMiscTemplate:PtrMiscTemplateType;
	i:ScsiDeviceType;
begin
	with isc_table[Sc]  do
	begin
		PtrMiscTemplate := addr(io_tmp_ptr^.drv_misc[1]);
		with PtrMiscTemplate^ do
		begin
			newbytes(MiscpScBlock, sizeof(SelectCodeBlockType));
			with MiscpScBlock^ do
			begin
				for i := 0 to 7 do
				begin
					DeviceSessionPtrs[i] := nil;
					DeviceSynchParms[i].SynchState := NoSynch;
					DeviceSynchParms[i].TMODvalue.tmod := 0;
				end;
				PtrScsiCard := card_ptr;
				PtrScsiChip := addr(PtrChar(PtrScsiCard)^,32);
				ScsiIntLevel := PtrScsiCard^.sc_reg.intlevel+3;
				ScsiSelectCode := Sc;
				DMAInProgress := FALSE;
				DMAChannel := -1;
			end;
			newbytes(MiscpSenseSpace, 256);
			MiscSenseLength := 0;
		end;
	end;
end;

{*************************************************************************
 *  osdGetScBlock
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Given a select code, return a pointer to the SelectCode block.
 *
 * On Output:  Ptr to SelectCodeBlock or Nil.
 *
 *************************************************************************}
Function osdGetScBlock(Sc:S_TYPE_ISC):PtrSelectCodeBlockType;
type
	ppScBlock = ^PtrSelectCodeBlockType;
begin
	with isc_table[Sc] do
	begin
		if (card_type = scsi_card) then
			osdGetScBlock := ppScBlock(addr(io_tmp_ptr^.drv_misc[1]))^
		else
			osdGetScBlock := Nil;
	end;
end;


{*************************************************************************
 *  osdLinkIsrRoutine
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Takes as paramters a select code and an ISR routine.  The ISR
 *      routine is linked into the O/S for the given Select Code.
 *
 *      The ISR routine address can be stored off of the SelectCodeBlock.
 *
 *      PWS implmentation:  Use a procedure that can recieve an ISRIB.
 *              From this get the select code, get the SelectCodeBlock,
 *              get and call the SCSI Driver ISR routine.
 *
 * On Output:  SCSI Driver ISR routine is linked into the O/S.
 *
 *************************************************************************}
Procedure osdScsiIsr(isribptr:pisrib);
var
	io_ptr:pio_tmp_ptr;
	pScBlock:PtrSelectCodeBlockType;
begin
	io_ptr := pio_tmp_ptr(isribptr);
	pScBlock := osdGetScBlock(io_ptr^.my_isc);
	call(pScBlock^.ScsiIsrProc, io_ptr^.my_isc);
end;

Procedure osdLinkIsrRoutine(IsrProc:ScsiIsrProcType; Sc:S_TYPE_ISC);
var
	pScBlock:PtrSelectCodeBlockType;
	pCard:PtrScsiCardType;
	p:ANYPTR;
begin
	pScBlock := osdGetScBlock(Sc);
	with isc_table[Sc], io_tmp_ptr^, pScBlock^, pScBlock^.PtrScsiCard^ do
	begin
		{
		  Check for ISR already in place.
		}
		if myisrib.intregaddr <> nil then  {isr already exits}
		begin
			{
			  unlink existing isr hook.
			}
			isrunlink(ScsiIntLevel, addr(myisrib));
		end;

		ScsiIsrProc := IsrProc;
		p := addr(sc_reg,1); {sc_reg.status, compiler won't let me otherwise}
		permisrlink(osdScsiIsr, p, hex('c0'), hex('c0'), ScsiIntLevel,
			addr(myisrib));
	end;
end;


{*************************************************************************
 *  osdDelay
 *************************************************************************
 *
 * On Input: Nothing is expected.
 *
 *
 * Functional Description:
 *
 *      Delay the given number of milliseconds.
 *
 * On Output:  Nothing is changed, however the given number of milliseconds
 *      has passed.
 *
 *************************************************************************}
Procedure osdDelay(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
	repeat until time_expired(timer);
end;


{*************************************************************************
 *  osdStartTimer & osdTimeExpired
 *************************************************************************
 *
 * On Input: Nothing is expected.
 *
 *
 * Functional Description:
 *
 *      These two routines are used to start a timer that will expire after
 *      a given number of milliseconds and then check to see if the timer
 *      has expired.
 *
 *      They are used to wait while waiting for an event to happen, thus
 *      preventing an eternal wait.
 *
 * On Output:  osdStartTimer: the timer has been started - this should not
 *      affect the driver in any way.  osdTimeExpired: returns TRUE if the
 *      timer has expired, FALSE otherwise.  This routine should have no
 *      affect on the driver.
 *
 *************************************************************************}
Procedure osdStartTimer(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
end;

Function osdTimeExpired:boolean;
begin
	osdTimeExpired := time_expired(timer);
end;



{*************************************************************************
 *  osdGetRunLevel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Returns the current run level of the 680x0 processor.
 *
 * On Output:
 *
 *
 *************************************************************************}
Function osdGetRunLevel:io_byte;
begin
	osdGetRunLevel := intlevel;
end;


{*************************************************************************
 *  osdSetRunLevel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Sets the current run level of the 680x0 processor to the requested
 *      level.
 *
 * On Output:  680x0 run level is at requested level.
 *
 *************************************************************************}
Procedure osdSetRunLevel(Level:io_byte);
begin
	setintlevel(level);
end;



{*************************************************************************
 *  Bit manipulation routintes
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *
 *
 * On Output:
 *
 *
 *************************************************************************}
Function osdBitOr(b1,b2:integer):integer;
begin
	osdBitOr := binior(b1,b2);
end;
Function osdBitAnd(b1,b2:integer):integer;
begin
	osdBitAnd := binand(b1,b2);
end;
Function osdBitLsL(b,Num:integer):integer;
begin
	osdBitLsL := binlsl(b,Num);
end;
Function osdBitLsR(b,Num:integer):integer;
begin
	 osdBitLsR := binlsr(b,Num);
end;


{*************************************************************************
 *  osdDMA32bit
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Determines if the current hardware supports 32 bit wide DMA.
 *
 * On Output:  TRUE if 32bit wide DMA is supported; FALSE otherwise.
 *             Modified to always FALSE due to hardware bug - 27AUG91 - CFB
 *
 *************************************************************************}
Function osdDMA32bit:boolean;
var
	io_dummy_word:io_word;
begin
	if dma_here then {from IODECLARATIONS}
	begin
		try
			io_dummy_word := ioread_word(3, hex('10'));
			if (io_dummy_word = hex('3230')) then  {ascii'2', '0'}
				osdDMA32bit := true
			else
				osdDMA32bit := false;
		recover
			osdDMA32bit := false;
	end
	else
		osdDMA32bit := false;
        osdDMA32bit := false; {always false due to hardware bug 27AUG91 - CFB}
end;


{*************************************************************************
 *  osdGetDMAChannel
 *************************************************************************
 *
 * On Input: nothing expected.
 *
 *
 * Functional Description:
 *
 *      Acquire, if possible, a DMA Channel from the operating system.
 *      Once acquired, this channel will be used by the SCSI Driver until
 *      the SCSI driver releases it.
 *
 * On Output:  0 for channel 0, 1 for channel 1, -1 for no channel.
 *
 *
 *************************************************************************}
Function osdGetDMAChannel(Sc:S_TYPE_ISC):integer;
begin
	osdGetDMAChannel := dma_request(isc_table[Sc].io_tmp_ptr);
end;


{*************************************************************************
 *  osdSetUpDMAChannel
 *************************************************************************
 *
 * On Input: DMA is present, and a Channel has been acquired.
 *           XferBlock.BufPtr is guaranteed to be on a word boundary and
 *           XferBlock.BufLen is guaranteed to be an even length.
 *
 * Functional Description:
 *
 *      Initialize and ARM the given DMA channel.  The DMA H/W should
 *      be set up to NOT interrupt.
 *
 *      The incomming
 *      DMA32bit parameter indicates if the SCSI H/W can handle 32 bit DMA or
 *      not, on exit DMA32bit should indicate if 32 bit DMA is being performed
 *      or not. (NOTE: SCSI driver expects either 16 or 32 bit DMA - 8 bit DMA
 *      is NOT acceptable).
 *
 *      XferBlock contains buffer address, length, and direction of transfer.
 *
 *      Because 16bit DMA can only transfer 128K max, the amount of data being
 *      transfered should be stored in the XferBlock (XferDMACount).  The value
 *      stored is the actual number of bytes the DMA channel will transfer.
 *
 * On Output:  DMA channel is initialized and ARMed.
 *
 *************************************************************************}
Procedure osdSetUpDMAChannel(Channel:integer; var DMA32bit:boolean; var XferBlock:XferBlockType);
var
	DMAPtr:PtrChar;
	Use32BitChannel:boolean;
	pChannel16:^Channel16BitType;
	pChannel32:^Channel32BitType;
	p32Gen:^Channel32BitGeneralType;
	i:integer;
begin
	{
	  Determine if a 16 or 32 bit channel should be used.
	}
	Use32BitChannel := osdDMA32bit;

	{
	  Determine what kind of DMA should be used, 16 or 32 bit.
	}
	if (DMA32bit) then
	begin
		DMA32bit := false;  {prove that SPU can do 32 bit first.}

		{is 32 bit wide DMA available in the SPU?}
		if (Use32BitChannel) then
		begin
			{is the buffer on a long word boundary?}
			i := integer(XferBlock.XferBufBlock.BufPtr);
			if (i mod 4) = 0 then
			begin
				{is the length divisible by 4?}
				i := XferBlock.XferBufBlock.BufLen;
				if (i mod 4) = 0 then
					DMA32bit := TRUE;
			end;
		end;
	end;

	osdKillDMA(Channel);

	DMAPtr := isc_table[3].card_ptr;
	if Use32BitChannel then
	begin
		{Get pointers to DMA channel}
		p32Gen     := addr(DMAPtr^,hex('10'));
		pChannel32 := addr(DMAPtr^,(Channel+1)*hex('100'));

		with p32Gen^, pChannel32^, XferBlock do
		begin
			{set bus control registers to 16 bit defaults}
			br := 0;
			bt := 2;

			{DMA address}
			address := XferBufBlock.BufPtr;

			{
			  DMA Count.
			  Can do the entire DMA in one go around, however the amount of transfers
			  depends on the width of the transfer.
			}
			XferDMACount := XferBufBlock.BufLen;
			if (DMA32bit) then
				count := (XferBufBlock.BufLen Div 4)-1
			else
				count := (XferBufBlock.BufLen Div 2)-1;

			{
			  Writing the start bit in the control register arms the DMA chip.
			}
			if (XferBlock.XferPhase = data_in_phase) then
			begin
				if DMA32bit then
					{start, 32bit, priority, input, word, no interrupt}
					cont_stat := hex('810A')
				else
					{start, 16bit, priority, input, word, no interrupt}
					cont_stat := hex ('800A');
			end
			else
			begin
				if DMA32bit then
					{start, 32bit, priority, output, word, no interrupt}
					cont_stat := hex('810E')
				else
					{start, 16bit, priority, output, word, no interrupt}
					cont_stat := hex('800E');
			end;
		end;
	end
	else
	begin
		{Get pointer to DMA channel}
		pChannel16 := addr(DMAPtr^, Channel*8);

		with pChannel16^, XferBlock do
		begin
			{DMA address}
			address := XferBufBlock.BufPtr;

			{DMA count (in words). DMA count is 1 less than total request. 128K transfer MAX.}
			if XferBufBlock.BufLen >= hex('20000') then {len >= 128K}
			begin
				XferDMACount := hex('20000');
				i := hex('ffff');
			end
			else
			begin
				XferDMACount := XferBufBlock.BufLen;
				i := (XferBufBlock.BufLen Div 2)-1;
			end;

			count := i;

			{
			  Writing the control register arms the DMA chip.
			}
			if (XferBlock.XferPhase = data_in_phase) then
				cont_stat := hex('000A')  {priority, input, word, no interrupt}
			else
				cont_stat := hex('000E'); {priority, output, word, no interrupt}
		end;
	end;
end;

{*************************************************************************
 *  osdKillDMA
 *************************************************************************
 *
 * On Input: DMA channel is actively transfering data.
 *
 *
 * Functional Description:
 *
 *      shutdown active DMA Channel.
 *      Force all data (instruction and data) in the processor's cache
 *      to be flushed.
 *
 * On Output:  active DMA channel is shutdown.
 *
 *
 *************************************************************************}
Procedure osdKillDMA(Channel:integer);
var
	io_dummy_word:io_word;
	pGen32:^Channel32bitGeneralType;
begin
	{
	  Kill the 16 bit channel by reading the channel address register.
	}
	io_dummy_word := ioread_word(3, Channel*8);

	{
	  Kill the 32 bit channel by specifically resetting the
	  appropriate channel.
	}
	pGen32 := isc_table[3].card_ptr;
	pGen32 := addr(pGen32^, hex('10'));
	if Channel = 0 then
		pGen32^.reset0 := true
	else
		pGen32^.reset1 := true;

	{
	  Flush the cache on 68020 and newer processors.
	   - this happens automatically with dma_release.
	}
end;


{*************************************************************************
 *  osdStopDMA
 *************************************************************************
 *
 * On Input: DMA channel is actively transfering data.
 *
 *
 * Functional Description:
 *
 *      Wait for the DMA channel to get to the desired count, and then kill it.
 *      (After an appropriate wait, kill the channel even if the desired count
 *       hasn't been reached).
 *
 * On Output:  TRUE: desired count reached and channel killed.
 *            FALSE: desired count NOT reached, channel killed.
 *
 *
 *************************************************************************}
Function osdStopDMA(Channel:integer; DMA32bit:boolean; StopCount:integer):boolean;
var
	DMAPtr:PtrChar;
	Use32BitChannel:boolean;
	pChannel32:^Channel32BitType;
	Count32:integer;
	pChannel16:^Channel16BitType;
	Count16:S_SHORT;
begin
	Use32BitChannel := osdDMA32bit;
	osdStopDMA := true;
	DMAPtr := isc_table[3].card_ptr;
	if Use32BitChannel then
	begin
		{Get pointer to 32 bit DMA channel}
		pChannel32 := addr(DMAPtr^,(Channel+1)*hex('100'));
		with pChannel32^ do
		begin
			if DMA32bit then
				Count32 := (StopCount Div 4) - 1
			else
				Count32 := (StopCount Div 2) - 1;

			if (count <> Count32) then
			begin
				{wait}
				osdStartTimer(one_second);
				repeat
				until (count <= Count32) or (osdTimeExpired);
				if (count <> Count32) then
					osdStopDMA := false;
			end;
		end;
	end
	else
	begin
		{Get pointer to DMA channel}
		pChannel16 := addr(DMAPtr^, Channel*8);
		with pChannel16^ do
		begin
			Count16 := ((StopCount Div 2) - 1) MOD hex('10000');

			if (count <> Count16) then
			begin
				{wait}
				osdStartTimer(one_second);
				repeat
				until (count <= Count16) or (osdTimeExpired);
				if (count <> Count16) then
					osdStopDMA := false;
			end;
		end;
	end;
	osdKillDMA(Channel);
end;


{*************************************************************************
 *  osdReleaseDMAChannel
 *************************************************************************
 *
 * On Input: Channel is NOT active.
 *
 *
 * Functional Description:
 *
 *      Give the channel back to the O/S.
 *
 * On Output:
 *
 *
 *************************************************************************}
Procedure osdReleaseDMAChannel(Sc:S_TYPE_ISC);
begin
	{release a DMA channel}
	dma_release(isc_table[Sc].io_tmp_ptr);
end;

end;
@


56.1
log
@Automatic bump of revision number for PWS version 3.25
@
text
@d129 1
a129 1
					DeviceSynchParms[i].SynchState := NeedSynch;
@


55.2
log
@Modified osdDMA32bit to always return false due to hardware bug.
When a 32 bit DMA terminates, it's kills any 16 bit DMA that may be running.
CFB
@
text
@@


55.1
log
@Automatic bump of revision number for PWS version 3.25A
@
text
@d378 1
a379 1
 *
d398 1
@


54.1
log
@Automatic bump of revision number for PWS version 3.24
@
text
@@


53.1
log
@Automatic bump of revision number for PWS version 3.24B
@
text
@@


52.1
log
@Automatic bump of revision number for PWS version 3.24A
@
text
@@


51.1
log
@Automatic bump of revision number for PWS version 3.24d
@
text
@@


50.1
log
@Automatic bump of revision number for PWS version 3.23c
@
text
@@


49.1
log
@Automatic bump of revision number for PWS version 3.24b
@
text
@@


48.1
log
@Automatic bump of revision number for PWS version 3.24a
@
text
@@


47.1
log
@Automatic bump of revision number for PWS version 3.23
@
text
@@


46.1
log
@Automatic bump of revision number for PWS version 3.23
@
text
@@


45.1
log
@Automatic bump of revision number for PWS version 3.23C
@
text
@@


44.1
log
@Automatic bump of revision number for PWS version 3.23B
@
text
@@


43.1
log
@Automatic bump of revision number for PWS version 3.23aA
@
text
@@


42.2
log
@Miscellaneous clean up that resulted from code review.
@
text
@@


42.1
log
@Automatic bump of revision number for PWS version 3.23e
@
text
@d214 1
a214 1
		  Check for interrupt already in place.
d615 1
a616 2
	cache_off;
	cache_on;
d666 1
a666 1
				until (count = Count32) or (osdTimeExpired);
d685 1
a685 1
				until (count = Count16) or (osdTimeExpired);
@


41.3
log
@Updated to initialize the sense block for SCSIIF.
@
text
@@


41.2
log
@If, when the SCSIDVR is first executed, and ISRIB exists for it, then unlink
that ISR and relink the new ISR.  This allows a new version of SCSIDVR to
be executed on top an existing one in memory.
@
text
@d107 7
d115 1
a115 3
	pByte:^io_byte;
	ppScBlock:^PtrSelectCodeBlockType;
	pScBlock:PtrSelectCodeBlockType;
d120 2
a121 4
		ppScBlock := addr(io_tmp_ptr^.drv_misc[1]);
		newbytes(ppScBlock^, sizeof(SelectCodeBlockType));
		pScBlock := ppScBlock^;
		with pScBlock^ do
d123 2
a124 1
			for i := 0 to 7 do
d126 12
a137 3
				DeviceSessionPtrs[i] := nil;
				DeviceSynchParms[i].SynchState := NeedSynch;
				DeviceSynchParms[i].TMODvalue.tmod := 0;
d139 2
a140 7
			PtrScsiCard := card_ptr;
			pByte := card_ptr;
			PtrScsiChip := addr(pByte^,32);
			ScsiIntLevel := PtrScsiCard^.sc_reg.intlevel+3;
			ScsiSelectCode := Sc;
			DMAInProgress := FALSE;
			DMAChannel := -1;
@


41.1
log
@Automatic bump of revision number for PWS version 3.23d
@
text
@d203 1
a203 1
	with isc_table[Sc], pScBlock^, pScBlock^.PtrScsiCard^ do
d205 11
d219 1
a219 1
			addr(io_tmp_ptr^.myisrib));
@


40.6
log
@cleaned up the osdGetDmaChannel code.
@
text
@@


40.5
log
@OSD_LL modified to reflect new DMA approach.

	1)  osdSetUpDMAChannel sets up AND ARMS the channel
	2)  if this is a 32 bit DMA interface, use that interface
	    even for a 16 bit transfer (performance gain).
	3)  osdARMDMAChannel is no longer required.

Fixed big in osdDMA32bit, which incorrectly reported 32 bit H/W when
only 16 bit was available.
@
text
@d401 1
a401 4
	if dma_here then
		osdGetDMAChannel := dma_request(isc_table[Sc].io_tmp_ptr)
	else
		osdGetDMAChannel := -1;
@


40.4
log
@Documented and reordered this module to make more sense.
Updated the DMA handling routines to modify the incoming count variable
to match the DMA chip instead of forcing the driver to have knowledge of
the DMA chip.
@
text
@d50 1
a50 2
	Procedure osdARMDMAChannel(Channel:integer; DMA32bit:boolean; var XferBlock:XferBlockType);
	Procedure osdKillDMA(Channel:integer; DMA32bit:boolean);
d370 4
a373 1
			osdDMA32bit := true;
d418 1
a418 1
 *      Initialize the given DMA channel, but DO NOT ARM it.  The DMA H/W should
d433 1
a433 1
 * On Output:  DMA channel only needs to be ARMed to begin a transfer.
d439 1
d446 5
d458 1
a458 1
		if (osdDMA32bit) then
d472 2
d475 1
a475 1
	if DMA32bit then
d490 5
a494 1
			{DMA count (in integers). DMA count is 1 less than total request. 4G transfer MAX.}
d496 26
a521 1
			count := (XferBufBlock.BufLen Div 4)-1;
a546 3
		end;
	end;
end;
d548 7
a554 20

{*************************************************************************
 *  osdARMDMAChannel
 *************************************************************************
 *
 * On Input: Channel has been acquired and initialized, all that remains is
 *      to ARM the channel to begin the transfer.
 *
 * Functional Description:
 *
 *      ARM the given DMA channel.
 *
 * On Output:  DMA transfer should commence.
 *
 *
 *************************************************************************}
Procedure osdARMDMAChannel(Channel:integer; DMA32bit:boolean; var XferBlock:XferBlockType);
type
	WordRecType = packed record
			control:S_SHORT;
a555 11
var
	pWord:^WordRecType;
	offset:integer;
begin
	if DMA32bit then
	begin
		offset := ((Channel+1)*hex('100'))+8;
	end
	else
	begin
		offset := (Channel*8)+6;
a556 7

	pWord := isc_table[3].card_ptr;
	pWord := addr(pWord^, offset);
	if (XferBlock.XferPhase = data_in_phase) then
		pWord^.control := hex('810A')   {priority, input, word, no interrupt}
	else
		pWord^.control := hex('810E');  {priority, output, word, no interrupt}
a558 1

d569 2
d576 1
a576 1
Procedure osdKillDMA(Channel:integer; DMA32bit:boolean);
d581 13
a593 9
	if DMA32bit then
	begin
		pGen32 := isc_table[3].card_ptr;
		pGen32 := addr(pGen32^, hex('10'));
		if Channel = 0 then
			pGen32^.reset0 := true
		else
			pGen32^.reset1 := true;
	end
d595 7
a601 3
	begin
		io_dummy_word := ioread_word(3, Channel*8);
	end;
d626 1
d632 1
d635 1
a635 1
	if DMA32bit then
d637 1
a637 1
		{Get pointer to DMA channel}
d641 5
a645 1
			Count32 := (StopCount Div 4) - 1;
d676 1
a676 1
	osdKillDMA(Channel, DMA32bit);
@


40.3
log
@Modifications for DMA support.
@
text
@d20 10
d32 1
a32 1
	Function osdTimeExpired:boolean;
d34 4
a37 4
	Procedure osdInitScBlock(Sc:S_TYPE_ISC);
	Function osdGetScBlock(Sc:S_TYPE_ISC):PtrSelectCodeBlockType;
	Procedure osdLinkIsrRoutine(IsrProc:ScsiIsrProcType; Sc:S_TYPE_ISC);
	Function osdGetRunLevel:io_byte;
d39 4
a42 4
	Function osdBitOr(b1,b2:integer):integer;
	Function osdBitAnd(b1,b2:integer):integer;
	Function osdBitLsL(b,Num:integer):integer;
	Function osdBitLsR(b,Num:integer):integer;
d44 5
a48 2
	Function osdDMA32bit:boolean;
	Function osdGetDMAChannel(Sc:S_TYPE_ISC):integer;
d52 1
a52 1
	Function osdStopDMA(Channel:integer; DMA32bit:boolean; Count32:integer):boolean;
d56 4
a87 6
Procedure osdDelay(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
	repeat until time_expired(timer);
end;
a89 5
Procedure osdStartTimer(ms:integer);
begin
	timer.time := ms;
	start_timer(timer);
end;
d91 16
a106 8

Function osdTimeExpired:boolean;
begin
	osdTimeExpired := time_expired(timer);
end;



d138 14
d165 22
d213 74
d292 16
d312 18
a338 2
VAR
  I:INTEGER;
a339 6
{
   FOR I:=1 TO Num DO
     B := b *2;
     osdBitLsL := B;
}

a342 2
VAR
  I:INTEGER;
a343 6
{
   FOR I:=1 TO Num DO
     B := b  DIV 2;
     osdBitLsR := B;
}

d348 15
d367 1
a367 2
	{ determine if the o/s can handle 32 bit dma. }
	if dma_here then
d379 18
d399 4
a402 2
	{attempt to get a DMA channel}
	osdGetDMAChannel := dma_request(isc_table[Sc].io_tmp_ptr);
d405 29
a433 9
{
  Set Up a DMA channel.
    - DMA is present, and a channel has been reserved.
    - Channel will be 0 or 1.
    - DMA32bit means the SCSI card can do 32 bit.  If 32 bit is available and the buffer is on
      a long word boundary, then 32 bit will be used.  DMA32bit should be set to false if 16 bit is used.
    - XferBlock contains buffer address, length, and direction of transfer.
    - Do NOT allow DMA interrupts!
}
d481 2
a482 3
			XferDMACount := (XferBufBlock.BufLen Div 4)-1;

			count := XferDMACount;
d496 5
a500 2
			if XferBufBlock.BufLen > hex('20000') then {len > 128K}
				XferDMACount := hex('ffff')
d502 4
a505 1
				XferDMACount := (XferBufBlock.BufLen Div 2)-1;
d507 1
a507 1
			count := XferDMACount;
d512 16
d554 16
d590 20
a609 1
Function osdStopDMA(Channel:integer; DMA32bit:boolean; Count32:integer):boolean;
d613 1
d625 1
d643 1
a643 1
			Count16 := Count MOD hex('10000');
d659 16
@


40.2
log
@Modifications to support synchronous protocol.
@
text
@d13 1
a13 1
import SCSI_DEFS, OSD_LLA, IODECLARATIONS, SYSGLOBALS, ISR, ASM, IOCOMASM;
d35 6
d43 25
d118 2
d207 2
d210 11
a220 1
	osdDMA32bit := false;
d223 189
a411 1
end {OSI_LL};
@


40.1
log
@Automatic bump of revision number for PWS version 3.23c
@
text
@d33 3
d79 2
a80 1
				DeviceSynchParms[i].DeviceSynched := false;
d170 6
@


39.1
log
@Automatic bump of revision number for PWS version 3.23b
@
text
@@


1.1
log
@Initial revision
@
text
@@
