/*====================================================================*
 *
 *    encapsulate and transmit as many Ethernet frames as possible 
 *    without overflowing the SPI write buffer;
 *
 *--------------------------------------------------------------------*/

function transmit frame do read write buffer space available register; 
while transmit queue is not empty and write buffer space is available do encapsulate transmit frame; 
write transmit frame to write buffer; 
if error then return failure; 
end if; 
update transmit statistics; 
remove frame from transmit queue; 
end while; 
return (success); 
end function; 

/*====================================================================*
 *
 *   read as many frames as possible from the read buffer; 
 *
 *--------------------------------------------------------------------*/

function receive frame do allocate an input buffer; 
if no memory available then return failure; 
end if; 
read read space available register; 
if read buffer is empty then return failure; 
end if; 
write frame length into buffer size register; 
if mode is legacy then send read command; 
end if; 
while read buffer is not empty do read read buffer into frame buffer; 
extract Ethernet frame from frame buffer; 
update read statistics; 
end while; 
return (success); 
end function; 

/*====================================================================*
 *
 *   state machine to manage QCA7000 SPI slave synchronization;
 *
 *--------------------------------------------------------------------*/

function synchronize SPI slave do allocate a static reset counter; 
if synchronization state is CPU on then read QCA7000 signature register; 
read QCA7000 signature register; 
if signature is invalid then set synchronization state to unknown; 
else read SPI write buffer space available register; 
if write buffer is empty then qca->SynchState = QCASPI_SYNC_READY; 
set synchronization state to ready; 
return; 
else set synchronization state to unknown; 
end if; 
end if; 
end if; 
if synchronization stats is ready then if mode is legacy then return; 
end if; 
read QCA7000 signature register; 
if signature is invalid then set synchronization state to unknown; 
return; 
end if; 
end if; 
if synchronization state is unknown then if mode is legacy then use GPIO to reset QCA7000; 
else read QCA7000 signature register; 
if signature is invalid then return; 
end if; 
set soc_core_reset bit in QCA SPI configuration register; 
end if set synchronization state to reset; 
clear reset counter; 
return; 
end if; 
if synchronization state is reset then increment reset counter; 
if reset counter exceeds reset limit then set synchronization state to unknown; 
end if; 
end if; 
return; 
end function; 

/*====================================================================*
 *   
 *   handle QCA7000 interrupts and transmit requests; interrupts are
 *   from the QCA7000; transmit requests are from the host computer;
 *   
 *--------------------------------------------------------------------*/

function interrupt serivce routine do while terminate is false do set thread state to interruptable; 
if no interrupts and synchronization state is synchronized and transmit queue is empty then allow other tasks to run; 
end if set thread state to busy; 
check synchronization state; 
if syncrhonization state is not synchronized then flush transmit queue; 
suspend for a while; 
end if; 
if interrupt occurred then disable SPI interrupts; 
read SPI interrupt cause register; 
if SPI interrupt cause is CPU on then update synchronization state; 
if synchronization state is synchronized then continue; 
end if; 
end if; 
if SPI interrupt cause is packet available then if synchronization state is synchronized then call receive frame function; 
end if; 
end if; 
if SPI interrupt cause is read buffer error then set synchronization state to unknown; 
continue; 
end if; 
if SPI interrupt cause is write buffer error then set synchronization state to unknown; 
continue; 
end if; 
clear SPI interrupt cause register; 
clear SPI interrupt register; 
end if; 
if transmit queue is not empty then call transmit frame function; 
end if; 
end while; 
set thread state to dormant; 
return; 
end function; 

/*====================================================================*
 *   
 *   basic interrupt handler; count interrupts since last service;
 *   wake up dormant service routine;
 *
 *--------------------------------------------------------------------*/

function interrupt handler do increment interrupt count; 
if thread is available and thread is dormant then wake up thread to service interrupt; 
end if; 
return (success); 
end function;