/fs/ocfs2/cluster/

wip-ecrts14-pgm The LITMUS^RT kernel.Bjoern Brandenburg
aboutsummaryrefslogblamecommitdiffstats
path: root/drivers/net/s2io.c
blob: 46ebf141ee5a15b62d0c16eeb77b86dc939a31a9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                                                                         
                                                                      










                                                                          



                                                                       


                                                                         
                                                                  
                                                                       
                                                                     

                                                                      
  

                                                                              
  

                                                                             

                                                                            

                                                                          
                                                                              
                                                                             
                                                                      





                                                                            







                                                                            

                                                                          




                         
                              








                              
                          
                            
                          


                      
 

                        
                   
                      
                    




                      
                              
 
                                 
                                            
                                                
 

                                         
 
                                                  








                                                                   
  



                                                                 



                                                                       





                                                                          
                                                                               
 
                                     

                                       




                                                                    










                                                
                                                          





                                 


                            
                              
                                    













                                     
                                      

                                 



                                     
                                


                                    



                             





                                    







                             
















                               
                           

                                    

                             
















                                



                                                              














                                    



                                                            


                                 
















                                          




                                      

  









                                                                               



                                                               





                                                                 



                                                               
                                         






                                                     


                                                                            


                                                                            
                                         


                                                
                                                     


                                                     
  



                                                                     
                           
                                       
                         
                                                     
                        
                                                     




                                                     



                                                     






                                                     
                                   
                         
                                                     






                                                     
                                                     

                                                     


                
  


                                                             
                              
















                                                     




                                                                        
                                 













                                            
                                                        
                                   
                                                             
                            
                                   
                      


                                                                  
                                    
                                    


                       
                                                   










                                                                           
 
  
                     
                                                              






                                                        


                                                    

















                                                                       

                                                                  







                                                
                                             
                          

                                          
                          
                           
 
                                     











                                                             
                                                                      
                                                                                 
                               

         
                                                           



                                                          
                                                                                


                                                                           



                                                                   
                                                                             



                                                                           

                                                                  
                                                   

                                                                  
                                                   

                                                  
                                                                   
 











                                                                        






                                                                       
                                                   
                                                                              
                                                   
                                                               








                                                                                


                                                                    

                                                                                   
                                                           
                                                                                  




                                                           
 
                                                                    


                                


                                                            

                                                     






                                                                           
                                                   



                                                                           
         
                                        
                                                      
            
                                                      

                                                   


                                                                       
                                                  


                                                                       
                                                  


                                                  

                                                               

                                                   
                                                        



                                                                        



                                                                          


                                                                        

                                                    
                                                                        


                                                    

                                                                
                                                                          

                                                                           

                                               







                                                                      


                                                

                                                                                   
                                         
                                                                         
                                                                       

                                                                                  
                                         
                                                                         

                                                                      
                                                                      

                                                                 



                                                             








                                                                            
                                                                             
                                                 
                                                      
                                               


                                                             
                                                                         


                                                                                
                                                       





















                                                                                


                         

                                                               
                                         



                                                           


                                                                         






                                            
                                                                   
                                    





                                                                   

                                              









                                                                          
                                     

                                    
                                          






                                        
                                                           






                                                                           
                                                             
                                       

                                                                       

                                                                 

                                                                  
                                                           

                                                                  

                                                           






                                                                           
                                           



                                                                        
                 
                                                       

         
                             
                                                   
                                                            
                                               



                                                                        



                                                                    
                                                                       


                 









                                                                       
                                                            





                                                                                
                         
                                                        
                 
         






                                                                

                                          

 
   


                         
                                                     
 
                                                         










                                                      




                                                        

                                                                               
                                                                
                                                  




                                         
 
                                                                  


                        
                                                    
 
                                                         









                                                      







                                                                        








                                                                               


                                                              


                                                                   


                                                                    


                                                                    


                                                                    


                                                                    


                                                                    








                                                                   
                                         
                                 


                                                                 




                                                
                                                         




                                          
                                     
                                    
                        
                                     
                     



                                        
                                                     
                                   



                                                                     









                                                                       


                                          
                    
                                       


















                                                             

                                                               
                                                                    
                                                                  

                                                            

                                  
                




                                                                  








































                                                                         



                                                           

                                                    

                                                           



                                                                          

                                                                   















                                                                        

                                                      


                            




                                                


                                                   

                                                                     


                                                               
                                                                     


                                                               
                                                                     


                                                               
                                                                     


                                                               
                                                                     


                                                               
                                                                     


                                                               
                                                                     


                                                               
                                                                     





                                                               
          

                                           
           






























































































                                                         
                                                      



                                                  












































                                                          
                                              



































































                                                         


                     
                               

                                                       



















                                                                          
        









                                                                        
                                       
                                                             
 




                                                    
          







                                                                         

                                                                  

                  

                                                             


                                                                    







                                                            
                                           
                                                                         

                                                              



                                              
                                                                        




                                                            
          



















                                                                        





                                                                            
 
                  




















                                                                                
                
 













                                                                                 
 
                                                    
 
                                                     






                                                              
                                                    
 

























                                                                                   
                 

         

                                                                 





                                                                   
                             







                                                          












                                                                  

                                                               






                                                                       
          






















                                                                 

                                                                       





                                                       





                                                                            




                                                                

                                                      



                                                    
         


                                                   

         

                       


                                         
                                                           
 

                                          




                                                 
 

                                                            



                                                                           

                                                                    




                                                                           
                                                         





                                                                         
                                    



                                                                
                          
                                                                    
                                                                      

                                              
                           










                                                                               
                          



                                                                            


                                                           







                                                                       







                                                                

                                                                              

                               
                                                   

                                                                              










                                                                       






                                                                
                          
                                                            
                                                                       


                                                            

                                                                            


















                                                                          

                                                                            









                                                                          




                                                        
                                                              
 
                          
                                                        


                                                     

                            

                                                                          
                                        

                                                                         
                                        

                 
                                                                          
                                                                      
                                                           
                                        

                                                                           
                                                                
                                        






                                                            
                                                                         
                                                                   

                                                                      
                                   


                                       
                                                      
 
                  
                                                        

                                                 
 






























                                                                    

         
















                                                                     




                                                                 
                



                                                                          
                                                 
 
                                                        




                                                          
                           




                                                   
                                   
                                   



                                                                        

                                                                           
                 




                                          
                                                         

                                          
                     
                                     






                                                   
                                                                               


                                                    

                                                            



                                                                            



                                                                  


                                                    





                                                                           
 






                                                   
          








                                                                     
                                                     





                                              

                                                                  





                                                              

                                                                    


                                             
                                           





                                                                           
          
                                                                      



                                                                      






                                              






                                                                            

                                                       

                                                    



                                                   
                                                             

         

                       


                                                                 

                                                                             
 
                                              
                            
                         


                       
                                                                  








                                                          
                                                                             












                                                                      
                                                              



                                                                     
                                                                    

                    
 

                                                
                                   
                
                               
                      





                                                 
                         
                 
                                     
                                    
                    





                                                                      
                                                                                 
                                           



                                                                                
                         



                                                                    

                                                                  


         

                                
                                    

                                                                    






                                                               
                                                         
                               
                          
                                     





                                        
                                                          

                                                   

                                                                 



                                                                 

 

                                                                           


                                          
                  

                                             
                                                          









                                                                             
                                             
                               


                                                                   

                                               
                                                                     







                                                                

                                                
                                  

                         






                                                                          

                                                                         






                                                                           
                                                             


                                          
                           
                                                 
                          
                      
                                     
                                    
                
                           
                            
                                        


                                        

                                                         
 
                                                                             
                                                                   
                                       
                                                                        
                                
                                                                          
 






                                                                        


                                                               
                                                               
                                                                     
                                          








                                                                             
                                                                     


                                                                    


                                                                      








                                                                          


                                                              
                                                                     
                                                     

                                 








                                                                        
 


                                          

                                                                        



                                                                      



                                                                   
                                                             
                                                       
                                                                          


                                                                                  












                                                                            
                                                             







                                                                            

                                                                   
                                                                                
                                                               

                                                                         
                                                                                   
                                                                  




                                                                       
                                                                      

                                             
                                                                                  


                                                                    
                                                                             

                                                                           
                                                                         


                                                                    















                                                                               
                 
                                                           

                                                              
                      

                                                          
                                                                          
 
                                                  






                                                                      




                                                        








                                                                        


                       




                                                                   


                                     











                                                                 
                                                                   




                                                              
                                                             



                                                               
                                                                   


                                                               
                                                                   


                                                               
                                                                   

                                                     
                                                             

                                                               
                                                                            

                                                               
                                                                  


                                                               
                                                                            
                                                    
                                                             





                                                       
   
                                          
                                 
                







                                                             
                                    
                                     
                                    




                                                   

                                                         
 



                                                                       








                                                                           
                                                                     








                                                                           

                                                         
                                         
                                             
                                     
                                    
                                                         
              
 
                                  


                                        



                                                   
 

                                                      

                                                   




                                                                          
                 















                                                                          
                                            
                                      
                                  

                 
      









                                                                          
                                  

                 
 
                                 
   
                                                   

                                          



                                                                              
   

                                                

                                         
                                    
                                                         
                                          







                                        
                                             

                                             
                                                                         




                                                                                
 
                                                                  
















                                                                          

                                          

                                                             
                                                                           

                                                                          



                 
                                                        
 
                                              
                                                                
                                             

                                                   
                            
                        

              

                                                         
                                                                    

                                                   
                       

         

                                               
                                                                          
                                         
                                                                               






                                                
                                    



                                                          

                                                               
                                                                         

                              




                                                                             
                                                   
                               
                 

                                                                
                                                                   




                                                                
                                                          
                                                                           
                                                                   
                                                               
                                                                
                                                                   
                                              
                                                     
                        
                                                                           
                                                                                     

                                                                
                                                                           


                                                                
                                                                           

                                                                       
                                    

                                                



                                                                     
                                            
                                                                             
                                    


                                                                            

                                                                               
 
                                          
                                                      
                              
                          


                                                                         


                                                           
                                                          







                                                             
                                   
 

   

                                                



                                                                     




                                         
                                                        
 
                                              
                                                                
                                                   
                            
                          
 
                                               

                                                                          







                                                            



                                                                     

                                                                     
                                                                    

                              
                                                                               
                         
                 
 
                                                                          






                                                                
                                                   



                                                

                                                             
                                                           


                                                     







                                      
   











                                                                                      

                                                        














































                                                                         

                                                        





































































































                                                                                               

                                                                  


















































































                                                                                  

                                                 
                                                                        
                                                                       

                                                                        







                                                                
                                                         
                                            

                

                                                       









                                                                             

                                                    





                                                                    

         




                                                                        

                                                             
                                                                    
                                             
                                                                    
                                                                   




                                                                             

                                                                             
                                 
                         
                        

                                                             


                 


                                                                   
                                                                       
                                                                       
                                                            
                                                     

                                                    
                                                                      




                                                                          
                                                                    










                                                       




























                                                                              



                                                                       
   
                                                            
                                                                           
                       


                                                                     



                                               

                                                                  
 
                                              

                  



                                                                         
                                    









                                                  
                 

                                  
                                      
                    
                                      
 


                                   

                   


















                                                                              
 

                                 

                                                                    
                                                                      




                                                       
                                            
 
                                                        
                  
                           



                                                             
 
                                                                               
                                                                          
 













                                                                            

                                       
        


                                              

                                                                
 






                                                                        
 






                                                                         
 


                                                       


                                                                 
                                                        
                                                  
                                                       
                                                                    
 

                                                             
 


                                                              
 


                                                                

                                                                     

                                                   



                                                   
                                                             

         








                                                                   


                                                                        



                                        

                                                              
                                      
                                                                




                                                          
                                                 

                                         
                                                        

                              
          


















































                                                                             
                                                     
                                                                       
                                                                






                                           

                                                                 










                                                   
                                                                
                                  
                                              

                                           
          
                                                                    
                                                                  














                                        
                                                                

                                              



                                           

                                                                 














                                                                             
                                                           
 
                                                         

















                                                                   
                                                   
 
                                                         


                  
                                                 










                                                                           
                                                 
 
                                                         



                               
                                                 














                                                                           
                                         
 
                                                         














































                                                                    
                                                  
 
                                                         


























































                                                                                      
                                    
                                                                            




                                                                             





                                                                                 
                                            

                               

                                                              











                                                                      



                                                               
   




                                                                          
                                                        




                                                                       
                                            
 
                                        

                    

                                                            


                               
                                

                                                  

                               

                                                                     
                                    



                                                               
                                   
                              
                                    



                               
 
               





                                                
                   














                                                                           
                                             
 
                                        
 

                                                                  
                           
 
















                                                                           
                                                                 
 
                                        

                                                                    

                                               
                            

                              
                                     
                                    
                         



                                       
                                                                     
                                               
                                                        
                                                                    

                                                            

                                   


                  
 






                                                                

                                                                          
                                                                           


                                                                            
                                                            

                                                                             
                                                                    




                                                            








                                                                          
                                              
                                                             
                                                  
                                                                      
         
                                                 



                                                             

                                                 
                                                
 




                                                          
                                           
                                          

                             
                                             















                                                                        
         
 



                                                             
                                        


                                              


                                                              


                                                           



                                                             
                                                               
                                                
                                                      


                                                
                                        

                                                                   
                                                    
                                                                           



                                                                     
                         
                                              
 

                                              

                 
                  

                                                                               
                                                                    

                                                            
                                                                      
                                                                    











                                                                        


                                     
                                                      




                                                      
                                                              



























                                                                              
                                                         

                                                              
                                        
              
                                     



















                                                                    

                                                 




                                 
                                                               
 

                                                            

                                 
 

                                               
 
                                 


                           
                                                               
 

                                                            





                                 
                                                       
 
                                                        






                                                       



                                                                               


                                                           
                                                            

                                                            
                                                            
                 

                                                             
                                                    






                                                              
 








                                                                      
 

                                                             





                                                                      




                                                              

                 
                                            

 



                                                            


                                                                      


                                                                         
                                                                     

                                                                   
                                                  

                                                              

                                                        
              
                       
                                     

                                    
                                 


                                       
          




                                                                    
                                                        



                                                  





                                                         
                                         

                                
 

                                                  
                                                                      
                                                         
                                                                               
                         

                                                                              








                                                                            


                                                                      

                                                                

                 
 




                                                                  

                                                              
 

                                                        
 

                                           


                                                                    

                                                             







                                                         
                                 



                           

                    
                                                
 
                                                        
















                                                                
                
                                                                                 



         
                                                             

                                           
                                                                         




                                                      
                                                                      
 

                                        

                                    
 


                                       




                                                                


                                                                        
                                                                     

                                                                         
                                    
                                                                     







                                                                          

                                                                         










                                                                          

                                                        















                                                                        
                                                               

                                                                               






                                                                     

                                                     




                                                                
                                                               

                                                                               















                                                                  






                                                           

                                              
                                                                     











                                                                      






                                                          

                                              
                                                                  





















                                                                           
                                                            






                                                                
                                                                           

                                                                               











                                                                               
                                     







                                                                  
                                                            






                                                                
                                                                           

                                                                               









                                                                          
                                                       

                                                                     
                                                                   
                               
                                                                     


                                          
                                                               
 

                                                        

                                         
                             
 
          

                                                                             
                       



                                        















                                                                          









                                                                     
                                                           
                                                                                







                                                                           
                                                      



                                                                                                 
                                                                        







                                                      
                                        











                                                                          
                                                       











                                                                              
                                        

















                                                                          

                                                                          











                                                                           
                                        
 



                                                                            


                                             




                                                   



                                                                         
                                                                          
                       
                                                                         














                                                                           
                                        











                                                              
                                                                        
                                                               


                                                                        



                                           

                                                        



                                           

                                                    















                                                                          
                                                                         

                                                                  
                                                               
                  
                                                                 







                                                               

                                                        



                                                        

                                                   













                                                                        
                                                
            
                                                       

                                      
                                                                        








                                                                          

                                                                          









                                                                          

                                                        










                                                                  
                                                                          









                                                                         
                                                             

                  

                                                        















                                                              
                                                                          


                                                                   
                         
               
                                                                      







                                                                       
                                                                 



                         
                                                        
 




                                                                                 
 








                                                                    
                 

         

                                                                 
                                                  


















                                                                     








                                                                           
                                                                           







                                                                       
                                                                         


                                   
                                                        
 
















                                                                                 
 




                                                                       
                                                        









                                                                     
                                        



                                      
                 
         

                   
                                               
 

                     










                                                                             
                                                 
 



                                            

















                                                                               















                                                                           


                                                                     
                        

 


                                                                                                       
                                                                      









                                                                       
                                                                      
 

                     
                                        




















                                                                           
                                                                      













                                                                       
                            
                                        






























                                                                             

                                                                          









                                                                           
                                                                    
 
                                                        
                               

                     

                                                










                                                                 




                                                


























                                                                 
                    


   
                                                                          




                                                                          
                                                                     




                
                                                                  

                     


                                         

                                          











                                                                         

                                      
                                                 



                                              
                                   



                                                                            
                         
         

                                           
                                             

                                                     


                                                   
 

                                                 
                         
                                              

                         
                                   



                                                                            
                         
         

                                           
                                             
 



                                                     
 


                                                     
 


                                                      
 









                                                       

                     
                    



                                                          
                                                                          
                      
                                                                          



                                                                   
                                                       



                                  
                                                                






















                                                                

                                                                          



                                                                           
                                                                        




                                 
                                                                
 
                                                        


                                             
                                
                          

                          
 
                     


   

                                                                           
                      
                                                               

                           
                                                                 




                                         
                                                                  
 
                                                        
                  
                                              






                                                  
                                                                 


























                                                           
                                                      

                                                         


                                                                         










                                                                  

                                                                         











                                                                  

                                                   



                            
                          
 



                                                             







                                                                           
                                                                











                                                                         
                                        



                                                    
                               
                                            




                                                             




                                                             






































                                                                     

                                                                  
 
                            





                                                                           
                                                                





                                                                         
                                                                      








                                                                          


                                                                            
                                                                         
                                                                    











                                                                       
                                                          







                                                                            

                                                                   





                                                                             
                                                                          
                                                                           

                                                                      









                                                                           


                                                                              




                                                                         











                                                                           







                                                                         
                                                

                                                                 

                                                                       
                                                     

                                                                    
                                                  
                                                          

                                                                   



                                                                           
















                                                                    


                                                                         

                                                                         


                                                                           
                                                              

















                                                                     























                                                                                


                                                            
















                                                                            



                                                                
                                                  

                                                                     
                  







                                                                      
         

                                   

 
                                                            




                                
                                                            
 
                                        


                             

                                                                     
 
                                        







                                

                                                      



                                   
                                                               


                               


                                                              
 


                                        




                                                              










                                                                         

         

                                                               












                                                

 
                                                                        








                                                  












                                                                    
 
                                                      
















                                                     

                                           

                                      








                                                        
                                          





                                                                           

                                                                          

   
                                                                        














                                                                         
                                                               
 
                                        






                                                                 
                           
                                 
                                   







                                                                          
                                                                



                                                                     








                                                                    
                                                                         
                                                                          
                                                                   







                                                                
                                        
                   
                                     





























                                                                          
                                                   
 
                                                                                  
                                          
                                                         


                           




                                

                                                                      
                                


                                            






                                                                    

                                             




                                                                         
                                                                      








                                                                              
                                 
                                                                



                                                                                
                         






                                                                         
                                                






                                                                       
                 
                                          

                                         

           
                      

 



                                                                             












                                                                        
                                                                   










                                                                                
                                                                    







                                                                                


                                                                   

                                                   

                                                                                
                                                   

                                               
                                                                    


                                                                      
                                                                    




                                                                             
                                                                    





                                                                            


                                                                   

                                                   




                                                                                
                                                                    


                                                                            
                                                                    


















                                                                               
                                                                    





                                                                              

                                                                        














                                                                           
                                                    

                                       
                                                         

                                                  
                                  
                                   
                                  





















                                                                             
                                                                        

                                                                             



                                                                          











                                                                        
                                             
 
                    
                                         
                    
 






                                                                          
         
 
                                                                                 
                            
 











                                                                           
                                                   
 






                                                                                











                                                                              





                                                                                











                                                                              
                         







                                                                             

                                                                    











                                                                             
                                              




























                                                                   









                                                              

 
                                                

                    
                                                        













                                                                         





                                                                     








                                                                              
                                                     

                                                                             












                                                                          

                       

                                               
                            



                                                    
                            
                                                    
 


                                        
                                             
 
                       
                                     

                                                               
                          




                                                                     
                               


                               

                                                                         















                                                                         






                                                  



                                      
                      
                                                                               





                                                                           


                                                                           
                               








                                           



                                    

                                                                        













                                                                        



                                             
   



                                                               
                                                                  



                                                               
                                                      
 
                                                                                  
                                         
 




                                
                           






                                                                  

                      

 

                                                  












                                                                     
                                        


                                                   
                                                                     









                                                                               
                 
                                                                           







                                                                           
                                                                           
 
                                             
                                                               


                                                     
                             
                                                              
                        
 
                       
 
                  




                                                                             















                                                                               
         
 



                                 

                                                                  
 









                                                                        
                                                                        








                                                                               





                                                                      
 

                                                                     

                                                            

                                                                           
                          




                                                                       



































                                                                             


                                                                   











                                                                            
                        

                                                                  







                                                       

                                                         

                                                                      
                                                                        





                                                                           
                        



                                                       
                 


                                    
         
                               
          
                                               









                                                                           

                                                                   



                 
                                                     















                                                                         







                                                      
                                                









                                                                            







                                                                                
                                               
 
                                      


                                                                          
                                          
                                                              
                                              
                                                             
                                          





                                                                

 













                                                                            


                                   















                                                                       
                                                                            


                                                                
 







                                                                                
   






























                                                                          
                                                   



                                                                            


                                                                           







                                                                    
                            
                               



                                 
                                                    
                  
                                     
                                    
                 
                                     
 

                                                           






                                                                       
                                                      

                                                                        
                                               
                                             





                                                                   
                                                             




                                                                        

                                                                  

                                                                       

















                                                                            

         
                                                      













                                                                        
                                               

                        
                                     
                                        






                                           
                                      
 





                                                         
                      
 


                                                          
          
                                                       


                                                                        





                                               





                                                            



                                                                           








                                                                     

                                                                   

                                 


                                                           
                                                  


















                                                                       


                                                             


                                                                        
                                     






                                                                
                                                                          







                                                                
                                                                          









                                                                             
                                                                                 











                                                      


                                                                 
 



                                                                   
                              
                         
 



                                            


                                                      
                                     
                                      
                                                             


                                                 


                                                

                                                         
 
                                 








                                                                            



















                                                                          

          






                                                                         
                                                       
                                                                              



                                                  






                                                                



                                                              


                                                   
          
                                                             
                                       




                                         

                                     


                                              
                                     
 


                                                                 

















                                                                         
                          
                                                                     



                                                                  
                                           
                                                                     





                                                           
                                                                  
                                                 
                                               
                               
                                                                          
                                       
                                               

                                             
         













                                                                             


                                                                    










                                                                                

                                                                         
                                     


                                                                       
                                    
                                                                         
 







                                                                                


                                                                     


                               











                                 







                                                               






                                    
                                     
                                                                         
                                                                         
                                                                        
                                                                         






                                                        
                            





                                                              

                               





                               







                                                               
                                    
                         
                                 









                                                                            
                                                 


   
                                               


                                                                                                  
                                    






                                              
 
                                                              
                                                        
































                                                                                
                                                                    













                                                                                
                                                          










                                                                            
          












                                                                       
                                                                    


                                       
                     
                                                                 
























                                                                       
                                                               










                                                                           
 



                                                             
                                            



                                            
                                                                        

                                                                         

                

                                                               







                                              




                                                                               
                                                                       
                                                                        







                                                                    
          






                                                                  
                                      










                                                                              
                                           






                                  

                                                                           















                                                                            
                                                   




































                                                                                
                                                           





































                                                                               
                                              
 
                                                        








                                                 



                                       

 

                                                                

                                       
                                            



                                            

                                           

                                                   
                                         
                             


                                                               
/************************************************************************
 * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC
 * Copyright(c) 2002-2005 Neterion Inc.

 * This software may be used and distributed according to the terms of
 * the GNU General Public License (GPL), incorporated herein by reference.
 * Drivers based on or derived from this code fall under the GPL and must
 * retain the authorship, copyright and license notice.  This file is not
 * a complete program and may only be used when the entire operating
 * system is licensed under the GPL.
 * See the file COPYING in this distribution for more information.
 *
 * Credits:
 * Jeff Garzik		: For pointing out the improper error condition
 *			  check in the s2io_xmit routine and also some
 *			  issues in the Tx watch dog function. Also for
 *			  patiently answering all those innumerable
 *			  questions regaring the 2.6 porting issues.
 * Stephen Hemminger	: Providing proper 2.6 porting mechanism for some
 *			  macros available only in 2.6 Kernel.
 * Francois Romieu	: For pointing out all code part that were
 *			  deprecated and also styling related comments.
 * Grant Grundler	: For helping me get rid of some Architecture
 *			  dependent code.
 * Christopher Hellwig	: Some more 2.6 specific issues in the driver.
 *
 * The module loadable parameters that are supported by the driver and a brief
 * explaination of all the variables.
 *
 * rx_ring_num : This can be used to program the number of receive rings used
 * in the driver.
 * rx_ring_sz: This defines the number of receive blocks each ring can have.
 *     This is also an array of size 8.
 * rx_ring_mode: This defines the operation mode of all 8 rings. The valid
 *		values are 1, 2 and 3.
 * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
 * tx_fifo_len: This too is an array of 8. Each element defines the number of
 * Tx descriptors that can be associated with each corresponding FIFO.
 * intr_type: This defines the type of interrupt. The values can be 0(INTA),
 *     1(MSI), 2(MSI_X). Default value is '0(INTA)'
 * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
 *     Possible values '1' for enable '0' for disable. Default is '0'
 * lro_max_pkts: This parameter defines maximum number of packets can be
 *     aggregated as a single large packet
 * napi: This parameter used to enable/disable NAPI (polling Rx)
 *     Possible values '1' for enable and '0' for disable. Default is '1'
 * ufo: This parameter used to enable/disable UDP Fragmentation Offload(UFO)
 *      Possible values '1' for enable and '0' for disable. Default is '0'
 * vlan_tag_strip: This can be used to enable or disable vlan stripping.
 *                 Possible values '1' for enable , '0' for disable.
 *                 Default is '2' - which means disable in promisc mode
 *                 and enable in non-promiscuous mode.
 ************************************************************************/

#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/stddef.h>
#include <linux/ioctl.h>
#include <linux/timex.h>
#include <linux/ethtool.h>
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/tcp.h>

#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/div64.h>
#include <asm/irq.h>

/* local include */
#include "s2io.h"
#include "s2io-regs.h"

#define DRV_VERSION "2.0.17.1"

/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
static char s2io_driver_version[] = DRV_VERSION;

static int rxd_size[4] = {32,48,48,64};
static int rxd_count[4] = {127,85,85,63};

static inline int RXD_IS_UP2DT(struct RxD_t *rxdp)
{
	int ret;

	ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) &&
		(GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK));

	return ret;
}

/*
 * Cards with following subsystem_id have a link state indication
 * problem, 600B, 600C, 600D, 640B, 640C and 640D.
 * macro below identifies these cards given the subsystem_id.
 */
#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \
	(dev_type == XFRAME_I_DEVICE) ?			\
		((((subid >= 0x600B) && (subid <= 0x600D)) || \
		 ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0

#define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \
				      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))
#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))
#define PANIC	1
#define LOW	2
static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring)
{
	struct mac_info *mac_control;

	mac_control = &sp->mac_control;
	if (rxb_size <= rxd_count[sp->rxd_mode])
		return PANIC;
	else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
		return  LOW;
	return 0;
}

/* Ethtool related variables and Macros. */
static char s2io_gstrings[][ETH_GSTRING_LEN] = {
	"Register test\t(offline)",
	"Eeprom test\t(offline)",
	"Link test\t(online)",
	"RLDRAM test\t(offline)",
	"BIST Test\t(offline)"
};

static char ethtool_xena_stats_keys[][ETH_GSTRING_LEN] = {
	{"tmac_frms"},
	{"tmac_data_octets"},
	{"tmac_drop_frms"},
	{"tmac_mcst_frms"},
	{"tmac_bcst_frms"},
	{"tmac_pause_ctrl_frms"},
	{"tmac_ttl_octets"},
	{"tmac_ucst_frms"},
	{"tmac_nucst_frms"},
	{"tmac_any_err_frms"},
	{"tmac_ttl_less_fb_octets"},
	{"tmac_vld_ip_octets"},
	{"tmac_vld_ip"},
	{"tmac_drop_ip"},
	{"tmac_icmp"},
	{"tmac_rst_tcp"},
	{"tmac_tcp"},
	{"tmac_udp"},
	{"rmac_vld_frms"},
	{"rmac_data_octets"},
	{"rmac_fcs_err_frms"},
	{"rmac_drop_frms"},
	{"rmac_vld_mcst_frms"},
	{"rmac_vld_bcst_frms"},
	{"rmac_in_rng_len_err_frms"},
	{"rmac_out_rng_len_err_frms"},
	{"rmac_long_frms"},
	{"rmac_pause_ctrl_frms"},
	{"rmac_unsup_ctrl_frms"},
	{"rmac_ttl_octets"},
	{"rmac_accepted_ucst_frms"},
	{"rmac_accepted_nucst_frms"},
	{"rmac_discarded_frms"},
	{"rmac_drop_events"},
	{"rmac_ttl_less_fb_octets"},
	{"rmac_ttl_frms"},
	{"rmac_usized_frms"},
	{"rmac_osized_frms"},
	{"rmac_frag_frms"},
	{"rmac_jabber_frms"},
	{"rmac_ttl_64_frms"},
	{"rmac_ttl_65_127_frms"},
	{"rmac_ttl_128_255_frms"},
	{"rmac_ttl_256_511_frms"},
	{"rmac_ttl_512_1023_frms"},
	{"rmac_ttl_1024_1518_frms"},
	{"rmac_ip"},
	{"rmac_ip_octets"},
	{"rmac_hdr_err_ip"},
	{"rmac_drop_ip"},
	{"rmac_icmp"},
	{"rmac_tcp"},
	{"rmac_udp"},
	{"rmac_err_drp_udp"},
	{"rmac_xgmii_err_sym"},
	{"rmac_frms_q0"},
	{"rmac_frms_q1"},
	{"rmac_frms_q2"},
	{"rmac_frms_q3"},
	{"rmac_frms_q4"},
	{"rmac_frms_q5"},
	{"rmac_frms_q6"},
	{"rmac_frms_q7"},
	{"rmac_full_q0"},
	{"rmac_full_q1"},
	{"rmac_full_q2"},
	{"rmac_full_q3"},
	{"rmac_full_q4"},
	{"rmac_full_q5"},
	{"rmac_full_q6"},
	{"rmac_full_q7"},
	{"rmac_pause_cnt"},
	{"rmac_xgmii_data_err_cnt"},
	{"rmac_xgmii_ctrl_err_cnt"},
	{"rmac_accepted_ip"},
	{"rmac_err_tcp"},
	{"rd_req_cnt"},
	{"new_rd_req_cnt"},
	{"new_rd_req_rtry_cnt"},
	{"rd_rtry_cnt"},
	{"wr_rtry_rd_ack_cnt"},
	{"wr_req_cnt"},
	{"new_wr_req_cnt"},
	{"new_wr_req_rtry_cnt"},
	{"wr_rtry_cnt"},
	{"wr_disc_cnt"},
	{"rd_rtry_wr_ack_cnt"},
	{"txp_wr_cnt"},
	{"txd_rd_cnt"},
	{"txd_wr_cnt"},
	{"rxd_rd_cnt"},
	{"rxd_wr_cnt"},
	{"txf_rd_cnt"},
	{"rxf_wr_cnt"}
};

static char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = {
	{"rmac_ttl_1519_4095_frms"},
	{"rmac_ttl_4096_8191_frms"},
	{"rmac_ttl_8192_max_frms"},
	{"rmac_ttl_gt_max_frms"},
	{"rmac_osized_alt_frms"},
	{"rmac_jabber_alt_frms"},
	{"rmac_gt_max_alt_frms"},
	{"rmac_vlan_frms"},
	{"rmac_len_discard"},
	{"rmac_fcs_discard"},
	{"rmac_pf_discard"},
	{"rmac_da_discard"},
	{"rmac_red_discard"},
	{"rmac_rts_discard"},
	{"rmac_ingm_full_discard"},
	{"link_fault_cnt"}
};

static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
	{"\n DRIVER STATISTICS"},
	{"single_bit_ecc_errs"},
	{"double_bit_ecc_errs"},
	{"parity_err_cnt"},
	{"serious_err_cnt"},
	{"soft_reset_cnt"},
	{"fifo_full_cnt"},
	{"ring_full_cnt"},
	("alarm_transceiver_temp_high"),
	("alarm_transceiver_temp_low"),
	("alarm_laser_bias_current_high"),
	("alarm_laser_bias_current_low"),
	("alarm_laser_output_power_high"),
	("alarm_laser_output_power_low"),
	("warn_transceiver_temp_high"),
	("warn_transceiver_temp_low"),
	("warn_laser_bias_current_high"),
	("warn_laser_bias_current_low"),
	("warn_laser_output_power_high"),
	("warn_laser_output_power_low"),
	("lro_aggregated_pkts"),
	("lro_flush_both_count"),
	("lro_out_of_sequence_pkts"),
	("lro_flush_due_to_max_pkts"),
	("lro_avg_aggr_pkts"),
};

#define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN
#define S2IO_ENHANCED_STAT_LEN sizeof(ethtool_enhanced_stats_keys)/ \
					ETH_GSTRING_LEN
#define S2IO_DRIVER_STAT_LEN sizeof(ethtool_driver_stats_keys)/ ETH_GSTRING_LEN

#define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN )
#define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN )

#define XFRAME_I_STAT_STRINGS_LEN ( XFRAME_I_STAT_LEN * ETH_GSTRING_LEN )
#define XFRAME_II_STAT_STRINGS_LEN ( XFRAME_II_STAT_LEN * ETH_GSTRING_LEN )

#define S2IO_TEST_LEN	sizeof(s2io_gstrings) / ETH_GSTRING_LEN
#define S2IO_STRINGS_LEN	S2IO_TEST_LEN * ETH_GSTRING_LEN

#define S2IO_TIMER_CONF(timer, handle, arg, exp)		\
			init_timer(&timer);			\
			timer.function = handle;		\
			timer.data = (unsigned long) arg;	\
			mod_timer(&timer, (jiffies + exp))	\

/* Add the vlan */
static void s2io_vlan_rx_register(struct net_device *dev,
					struct vlan_group *grp)
{
	struct s2io_nic *nic = dev->priv;
	unsigned long flags;

	spin_lock_irqsave(&nic->tx_lock, flags);
	nic->vlgrp = grp;
	spin_unlock_irqrestore(&nic->tx_lock, flags);
}

/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
int vlan_strip_flag;

/* Unregister the vlan */
static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
{
	struct s2io_nic *nic = dev->priv;
	unsigned long flags;

	spin_lock_irqsave(&nic->tx_lock, flags);
	vlan_group_set_device(nic->vlgrp, vid, NULL);
	spin_unlock_irqrestore(&nic->tx_lock, flags);
}

/*
 * Constants to be programmed into the Xena's registers, to configure
 * the XAUI.
 */

#define	END_SIGN	0x0
static const u64 herc_act_dtx_cfg[] = {
	/* Set address */
	0x8000051536750000ULL, 0x80000515367500E0ULL,
	/* Write data */
	0x8000051536750004ULL, 0x80000515367500E4ULL,
	/* Set address */
	0x80010515003F0000ULL, 0x80010515003F00E0ULL,
	/* Write data */
	0x80010515003F0004ULL, 0x80010515003F00E4ULL,
	/* Set address */
	0x801205150D440000ULL, 0x801205150D4400E0ULL,
	/* Write data */
	0x801205150D440004ULL, 0x801205150D4400E4ULL,
	/* Set address */
	0x80020515F2100000ULL, 0x80020515F21000E0ULL,
	/* Write data */
	0x80020515F2100004ULL, 0x80020515F21000E4ULL,
	/* Done */
	END_SIGN
};

static const u64 xena_dtx_cfg[] = {
	/* Set address */
	0x8000051500000000ULL, 0x80000515000000E0ULL,
	/* Write data */
	0x80000515D9350004ULL, 0x80000515D93500E4ULL,
	/* Set address */
	0x8001051500000000ULL, 0x80010515000000E0ULL,
	/* Write data */
	0x80010515001E0004ULL, 0x80010515001E00E4ULL,
	/* Set address */
	0x8002051500000000ULL, 0x80020515000000E0ULL,
	/* Write data */
	0x80020515F2100004ULL, 0x80020515F21000E4ULL,
	END_SIGN
};

/*
 * Constants for Fixing the MacAddress problem seen mostly on
 * Alpha machines.
 */
static const u64 fix_mac[] = {
	0x0060000000000000ULL, 0x0060600000000000ULL,
	0x0040600000000000ULL, 0x0000600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0060600000000000ULL,
	0x0020600000000000ULL, 0x0000600000000000ULL,
	0x0040600000000000ULL, 0x0060600000000000ULL,
	END_SIGN
};

MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);


/* Module Loadable parameters. */
S2IO_PARM_INT(tx_fifo_num, 1);
S2IO_PARM_INT(rx_ring_num, 1);


S2IO_PARM_INT(rx_ring_mode, 1);
S2IO_PARM_INT(use_continuous_tx_intrs, 1);
S2IO_PARM_INT(rmac_pause_time, 0x100);
S2IO_PARM_INT(mc_pause_threshold_q0q3, 187);
S2IO_PARM_INT(mc_pause_threshold_q4q7, 187);
S2IO_PARM_INT(shared_splits, 0);
S2IO_PARM_INT(tmac_util_period, 5);
S2IO_PARM_INT(rmac_util_period, 5);
S2IO_PARM_INT(bimodal, 0);
S2IO_PARM_INT(l3l4hdr_size, 128);
/* Frequency of Rx desc syncs expressed as power of 2 */
S2IO_PARM_INT(rxsync_frequency, 3);
/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
S2IO_PARM_INT(intr_type, 0);
/* Large receive offload feature */
S2IO_PARM_INT(lro, 0);
/* Max pkts to be aggregated by LRO at one time. If not specified,
 * aggregation happens until we hit max IP pkt size(64K)
 */
S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
S2IO_PARM_INT(indicate_max_pkts, 0);

S2IO_PARM_INT(napi, 1);
S2IO_PARM_INT(ufo, 0);
S2IO_PARM_INT(vlan_tag_strip, NO_STRIP_IN_PROMISC);

static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
static unsigned int rx_ring_sz[MAX_RX_RINGS] =
    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
static unsigned int rts_frm_len[MAX_RX_RINGS] =
    {[0 ...(MAX_RX_RINGS - 1)] = 0 };

module_param_array(tx_fifo_len, uint, NULL, 0);
module_param_array(rx_ring_sz, uint, NULL, 0);
module_param_array(rts_frm_len, uint, NULL, 0);

/*
 * S2IO device table.
 * This table lists all the devices that this driver supports.
 */
static struct pci_device_id s2io_tbl[] __devinitdata = {
	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN,
	 PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,
	 PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN,
         PCI_ANY_ID, PCI_ANY_ID},
        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI,
         PCI_ANY_ID, PCI_ANY_ID},
	{0,}
};

MODULE_DEVICE_TABLE(pci, s2io_tbl);

static struct pci_driver s2io_driver = {
      .name = "S2IO",
      .id_table = s2io_tbl,
      .probe = s2io_init_nic,
      .remove = __devexit_p(s2io_rem_nic),
};

/* A simplifier macro used both by init and free shared_mem Fns(). */
#define TXD_MEM_PAGE_CNT(len, per_each) ((len+per_each - 1) / per_each)

/**
 * init_shared_mem - Allocation and Initialization of Memory
 * @nic: Device private variable.
 * Description: The function allocates all the memory areas shared
 * between the NIC and the driver. This includes Tx descriptors,
 * Rx descriptors and the statistics block.
 */

static int init_shared_mem(struct s2io_nic *nic)
{
	u32 size;
	void *tmp_v_addr, *tmp_v_addr_next;
	dma_addr_t tmp_p_addr, tmp_p_addr_next;
	struct RxD_block *pre_rxd_blk = NULL;
	int i, j, blk_cnt;
	int lst_size, lst_per_page;
	struct net_device *dev = nic->dev;
	unsigned long tmp;
	struct buffAdd *ba;

	struct mac_info *mac_control;
	struct config_param *config;

	mac_control = &nic->mac_control;
	config = &nic->config;


	/* Allocation and initialization of TXDLs in FIOFs */
	size = 0;
	for (i = 0; i < config->tx_fifo_num; i++) {
		size += config->tx_cfg[i].fifo_len;
	}
	if (size > MAX_AVAILABLE_TXDS) {
		DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, ");
		DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
		return -EINVAL;
	}

	lst_size = (sizeof(struct TxD) * config->max_txds);
	lst_per_page = PAGE_SIZE / lst_size;

	for (i = 0; i < config->tx_fifo_num; i++) {
		int fifo_len = config->tx_cfg[i].fifo_len;
		int list_holder_size = fifo_len * sizeof(struct list_info_hold);
		mac_control->fifos[i].list_info = kmalloc(list_holder_size,
							  GFP_KERNEL);
		if (!mac_control->fifos[i].list_info) {
			DBG_PRINT(ERR_DBG,
				  "Malloc failed for list_info\n");
			return -ENOMEM;
		}
		memset(mac_control->fifos[i].list_info, 0, list_holder_size);
	}
	for (i = 0; i < config->tx_fifo_num; i++) {
		int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
						lst_per_page);
		mac_control->fifos[i].tx_curr_put_info.offset = 0;
		mac_control->fifos[i].tx_curr_put_info.fifo_len =
		    config->tx_cfg[i].fifo_len - 1;
		mac_control->fifos[i].tx_curr_get_info.offset = 0;
		mac_control->fifos[i].tx_curr_get_info.fifo_len =
		    config->tx_cfg[i].fifo_len - 1;
		mac_control->fifos[i].fifo_no = i;
		mac_control->fifos[i].nic = nic;
		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;

		for (j = 0; j < page_num; j++) {
			int k = 0;
			dma_addr_t tmp_p;
			void *tmp_v;
			tmp_v = pci_alloc_consistent(nic->pdev,
						     PAGE_SIZE, &tmp_p);
			if (!tmp_v) {
				DBG_PRINT(ERR_DBG,
					  "pci_alloc_consistent ");
				DBG_PRINT(ERR_DBG, "failed for TxDL\n");
				return -ENOMEM;
			}
			/* If we got a zero DMA address(can happen on
			 * certain platforms like PPC), reallocate.
			 * Store virtual address of page we don't want,
			 * to be freed later.
			 */
			if (!tmp_p) {
				mac_control->zerodma_virt_addr = tmp_v;
				DBG_PRINT(INIT_DBG,
				"%s: Zero DMA address for TxDL. ", dev->name);
				DBG_PRINT(INIT_DBG,
				"Virtual address %p\n", tmp_v);
				tmp_v = pci_alloc_consistent(nic->pdev,
						     PAGE_SIZE, &tmp_p);
				if (!tmp_v) {
					DBG_PRINT(ERR_DBG,
					  "pci_alloc_consistent ");
					DBG_PRINT(ERR_DBG, "failed for TxDL\n");
					return -ENOMEM;
				}
			}
			while (k < lst_per_page) {
				int l = (j * lst_per_page) + k;
				if (l == config->tx_cfg[i].fifo_len)
					break;
				mac_control->fifos[i].list_info[l].list_virt_addr =
				    tmp_v + (k * lst_size);
				mac_control->fifos[i].list_info[l].list_phy_addr =
				    tmp_p + (k * lst_size);
				k++;
			}
		}
	}

	nic->ufo_in_band_v = kcalloc(size, sizeof(u64), GFP_KERNEL);
	if (!nic->ufo_in_band_v)
		return -ENOMEM;

	/* Allocation and initialization of RXDs in Rings */
	size = 0;
	for (i = 0; i < config->rx_ring_num; i++) {
		if (config->rx_cfg[i].num_rxd %
		    (rxd_count[nic->rxd_mode] + 1)) {
			DBG_PRINT(ERR_DBG, "%s: RxD count of ", dev->name);
			DBG_PRINT(ERR_DBG, "Ring%d is not a multiple of ",
				  i);
			DBG_PRINT(ERR_DBG, "RxDs per Block");
			return FAILURE;
		}
		size += config->rx_cfg[i].num_rxd;
		mac_control->rings[i].block_count =
			config->rx_cfg[i].num_rxd /
			(rxd_count[nic->rxd_mode] + 1 );
		mac_control->rings[i].pkt_cnt = config->rx_cfg[i].num_rxd -
			mac_control->rings[i].block_count;
	}
	if (nic->rxd_mode == RXD_MODE_1)
		size = (size * (sizeof(struct RxD1)));
	else
		size = (size * (sizeof(struct RxD3)));

	for (i = 0; i < config->rx_ring_num; i++) {
		mac_control->rings[i].rx_curr_get_info.block_index = 0;
		mac_control->rings[i].rx_curr_get_info.offset = 0;
		mac_control->rings[i].rx_curr_get_info.ring_len =
		    config->rx_cfg[i].num_rxd - 1;
		mac_control->rings[i].rx_curr_put_info.block_index = 0;
		mac_control->rings[i].rx_curr_put_info.offset = 0;
		mac_control->rings[i].rx_curr_put_info.ring_len =
		    config->rx_cfg[i].num_rxd - 1;
		mac_control->rings[i].nic = nic;
		mac_control->rings[i].ring_no = i;

		blk_cnt = config->rx_cfg[i].num_rxd /
				(rxd_count[nic->rxd_mode] + 1);
		/*  Allocating all the Rx blocks */
		for (j = 0; j < blk_cnt; j++) {
			struct rx_block_info *rx_blocks;
			int l;

			rx_blocks = &mac_control->rings[i].rx_blocks[j];
			size = SIZE_OF_BLOCK; //size is always page size
			tmp_v_addr = pci_alloc_consistent(nic->pdev, size,
							  &tmp_p_addr);
			if (tmp_v_addr == NULL) {
				/*
				 * In case of failure, free_shared_mem()
				 * is called, which should free any
				 * memory that was alloced till the
				 * failure happened.
				 */
				rx_blocks->block_virt_addr = tmp_v_addr;
				return -ENOMEM;
			}
			memset(tmp_v_addr, 0, size);
			rx_blocks->block_virt_addr = tmp_v_addr;
			rx_blocks->block_dma_addr = tmp_p_addr;
			rx_blocks->rxds = kmalloc(sizeof(struct rxd_info)*
						  rxd_count[nic->rxd_mode],
						  GFP_KERNEL);
			if (!rx_blocks->rxds)
				return -ENOMEM;
			for (l=0; l<rxd_count[nic->rxd_mode];l++) {
				rx_blocks->rxds[l].virt_addr =
					rx_blocks->block_virt_addr +
					(rxd_size[nic->rxd_mode] * l);
				rx_blocks->rxds[l].dma_addr =
					rx_blocks->block_dma_addr +
					(rxd_size[nic->rxd_mode] * l);
			}
		}
		/* Interlinking all Rx Blocks */
		for (j = 0; j < blk_cnt; j++) {
			tmp_v_addr =
				mac_control->rings[i].rx_blocks[j].block_virt_addr;
			tmp_v_addr_next =
				mac_control->rings[i].rx_blocks[(j + 1) %
					      blk_cnt].block_virt_addr;
			tmp_p_addr =
				mac_control->rings[i].rx_blocks[j].block_dma_addr;
			tmp_p_addr_next =
				mac_control->rings[i].rx_blocks[(j + 1) %
					      blk_cnt].block_dma_addr;

			pre_rxd_blk = (struct RxD_block *) tmp_v_addr;
			pre_rxd_blk->reserved_2_pNext_RxD_block =
			    (unsigned long) tmp_v_addr_next;
			pre_rxd_blk->pNext_RxD_Blk_physical =
			    (u64) tmp_p_addr_next;
		}
	}
	if (nic->rxd_mode >= RXD_MODE_3A) {
		/*
		 * Allocation of Storages for buffer addresses in 2BUFF mode
		 * and the buffers as well.
		 */
		for (i = 0; i < config->rx_ring_num; i++) {
			blk_cnt = config->rx_cfg[i].num_rxd /
			   (rxd_count[nic->rxd_mode]+ 1);
			mac_control->rings[i].ba =
				kmalloc((sizeof(struct buffAdd *) * blk_cnt),
				     GFP_KERNEL);
			if (!mac_control->rings[i].ba)
				return -ENOMEM;
			for (j = 0; j < blk_cnt; j++) {
				int k = 0;
				mac_control->rings[i].ba[j] =
					kmalloc((sizeof(struct buffAdd) *
						(rxd_count[nic->rxd_mode] + 1)),
						GFP_KERNEL);
				if (!mac_control->rings[i].ba[j])
					return -ENOMEM;
				while (k != rxd_count[nic->rxd_mode]) {
					ba = &mac_control->rings[i].ba[j][k];

					ba->ba_0_org = (void *) kmalloc
					    (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);
					if (!ba->ba_0_org)
						return -ENOMEM;
					tmp = (unsigned long)ba->ba_0_org;
					tmp += ALIGN_SIZE;
					tmp &= ~((unsigned long) ALIGN_SIZE);
					ba->ba_0 = (void *) tmp;

					ba->ba_1_org = (void *) kmalloc
					    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);
					if (!ba->ba_1_org)
						return -ENOMEM;
					tmp = (unsigned long) ba->ba_1_org;
					tmp += ALIGN_SIZE;
					tmp &= ~((unsigned long) ALIGN_SIZE);
					ba->ba_1 = (void *) tmp;
					k++;
				}
			}
		}
	}

	/* Allocation and initialization of Statistics block */
	size = sizeof(struct stat_block);
	mac_control->stats_mem = pci_alloc_consistent
	    (nic->pdev, size, &mac_control->stats_mem_phy);

	if (!mac_control->stats_mem) {
		/*
		 * In case of failure, free_shared_mem() is called, which
		 * should free any memory that was alloced till the
		 * failure happened.
		 */
		return -ENOMEM;
	}
	mac_control->stats_mem_sz = size;

	tmp_v_addr = mac_control->stats_mem;
	mac_control->stats_info = (struct stat_block *) tmp_v_addr;
	memset(tmp_v_addr, 0, size);
	DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,
		  (unsigned long long) tmp_p_addr);

	return SUCCESS;
}

/**
 * free_shared_mem - Free the allocated Memory
 * @nic:  Device private variable.
 * Description: This function is to free all memory locations allocated by
 * the init_shared_mem() function and return it to the kernel.
 */

static void free_shared_mem(struct s2io_nic *nic)
{
	int i, j, blk_cnt, size;
	void *tmp_v_addr;
	dma_addr_t tmp_p_addr;
	struct mac_info *mac_control;
	struct config_param *config;
	int lst_size, lst_per_page;
	struct net_device *dev = nic->dev;

	if (!nic)
		return;

	mac_control = &nic->mac_control;
	config = &nic->config;

	lst_size = (sizeof(struct TxD) * config->max_txds);
	lst_per_page = PAGE_SIZE / lst_size;

	for (i = 0; i < config->tx_fifo_num; i++) {
		int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,
						lst_per_page);
		for (j = 0; j < page_num; j++) {
			int mem_blks = (j * lst_per_page);
			if (!mac_control->fifos[i].list_info)
				return;
			if (!mac_control->fifos[i].list_info[mem_blks].
				 list_virt_addr)
				break;
			pci_free_consistent(nic->pdev, PAGE_SIZE,
					    mac_control->fifos[i].
					    list_info[mem_blks].
					    list_virt_addr,
					    mac_control->fifos[i].
					    list_info[mem_blks].
					    list_phy_addr);
		}
		/* If we got a zero DMA address during allocation,
		 * free the page now
		 */
		if (mac_control->zerodma_virt_addr) {
			pci_free_consistent(nic->pdev, PAGE_SIZE,
					    mac_control->zerodma_virt_addr,
					    (dma_addr_t)0);
			DBG_PRINT(INIT_DBG,
			  	"%s: Freeing TxDL with zero DMA addr. ",
				dev->name);
			DBG_PRINT(INIT_DBG, "Virtual address %p\n",
				mac_control->zerodma_virt_addr);
		}
		kfree(mac_control->fifos[i].list_info);
	}

	size = SIZE_OF_BLOCK;
	for (i = 0; i < config->rx_ring_num; i++) {
		blk_cnt = mac_control->rings[i].block_count;
		for (j = 0; j < blk_cnt; j++) {
			tmp_v_addr = mac_control->rings[i].rx_blocks[j].
				block_virt_addr;
			tmp_p_addr = mac_control->rings[i].rx_blocks[j].
				block_dma_addr;
			if (tmp_v_addr == NULL)
				break;
			pci_free_consistent(nic->pdev, size,
					    tmp_v_addr, tmp_p_addr);
			kfree(mac_control->rings[i].rx_blocks[j].rxds);
		}
	}

	if (nic->rxd_mode >= RXD_MODE_3A) {
		/* Freeing buffer storage addresses in 2BUFF mode. */
		for (i = 0; i < config->rx_ring_num; i++) {
			blk_cnt = config->rx_cfg[i].num_rxd /
			    (rxd_count[nic->rxd_mode] + 1);
			for (j = 0; j < blk_cnt; j++) {
				int k = 0;
				if (!mac_control->rings[i].ba[j])
					continue;
				while (k != rxd_count[nic->rxd_mode]) {
					struct buffAdd *ba =
						&mac_control->rings[i].ba[j][k];
					kfree(ba->ba_0_org);
					kfree(ba->ba_1_org);
					k++;
				}
				kfree(mac_control->rings[i].ba[j]);
			}
			kfree(mac_control->rings[i].ba);
		}
	}

	if (mac_control->stats_mem) {
		pci_free_consistent(nic->pdev,
				    mac_control->stats_mem_sz,
				    mac_control->stats_mem,
				    mac_control->stats_mem_phy);
	}
	if (nic->ufo_in_band_v)
		kfree(nic->ufo_in_band_v);
}

/**
 * s2io_verify_pci_mode -
 */

static int s2io_verify_pci_mode(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	register u64 val64 = 0;
	int     mode;

	val64 = readq(&bar0->pci_mode);
	mode = (u8)GET_PCI_MODE(val64);

	if ( val64 & PCI_MODE_UNKNOWN_MODE)
		return -1;      /* Unknown PCI mode */
	return mode;
}

#define NEC_VENID   0x1033
#define NEC_DEVID   0x0125
static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
{
	struct pci_dev *tdev = NULL;
	while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
		if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) {
			if (tdev->bus == s2io_pdev->bus->parent)
				pci_dev_put(tdev);
				return 1;
		}
	}
	return 0;
}

static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};
/**
 * s2io_print_pci_mode -
 */
static int s2io_print_pci_mode(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	register u64 val64 = 0;
	int	mode;
	struct config_param *config = &nic->config;

	val64 = readq(&bar0->pci_mode);
	mode = (u8)GET_PCI_MODE(val64);

	if ( val64 & PCI_MODE_UNKNOWN_MODE)
		return -1;	/* Unknown PCI mode */

	config->bus_speed = bus_speed[mode];

	if (s2io_on_nec_bridge(nic->pdev)) {
		DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
							nic->dev->name);
		return mode;
	}

	if (val64 & PCI_MODE_32_BITS) {
		DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
	} else {
		DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name);
	}

	switch(mode) {
		case PCI_MODE_PCI_33:
			DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
			break;
		case PCI_MODE_PCI_66:
			DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
			break;
		case PCI_MODE_PCIX_M1_66:
			DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
			break;
		case PCI_MODE_PCIX_M1_100:
			DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
			break;
		case PCI_MODE_PCIX_M1_133:
			DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
			break;
		case PCI_MODE_PCIX_M2_66:
			DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
			break;
		case PCI_MODE_PCIX_M2_100:
			DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
			break;
		case PCI_MODE_PCIX_M2_133:
			DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
			break;
		default:
			return -1;	/* Unsupported bus speed */
	}

	return mode;
}

/**
 *  init_nic - Initialization of hardware
 *  @nic: device peivate variable
 *  Description: The function sequentially configures every block
 *  of the H/W from their reset values.
 *  Return Value:  SUCCESS on success and
 *  '-1' on failure (endian settings incorrect).
 */

static int init_nic(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	struct net_device *dev = nic->dev;
	register u64 val64 = 0;
	void __iomem *add;
	u32 time;
	int i, j;
	struct mac_info *mac_control;
	struct config_param *config;
	int dtx_cnt = 0;
	unsigned long long mem_share;
	int mem_size;

	mac_control = &nic->mac_control;
	config = &nic->config;

	/* to set the swapper controle on the card */
	if(s2io_set_swapper(nic)) {
		DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");
		return -1;
	}

	/*
	 * Herc requires EOI to be removed from reset before XGXS, so..
	 */
	if (nic->device_type & XFRAME_II_DEVICE) {
		val64 = 0xA500000000ULL;
		writeq(val64, &bar0->sw_reset);
		msleep(500);
		val64 = readq(&bar0->sw_reset);
	}

	/* Remove XGXS from reset state */
	val64 = 0;
	writeq(val64, &bar0->sw_reset);
	msleep(500);
	val64 = readq(&bar0->sw_reset);

	/*  Enable Receiving broadcasts */
	add = &bar0->mac_cfg;
	val64 = readq(&bar0->mac_cfg);
	val64 |= MAC_RMAC_BCAST_ENABLE;
	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
	writel((u32) val64, add);
	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
	writel((u32) (val64 >> 32), (add + 4));

	/* Read registers in all blocks */
	val64 = readq(&bar0->mac_int_mask);
	val64 = readq(&bar0->mc_int_mask);
	val64 = readq(&bar0->xgxs_int_mask);

	/*  Set MTU */
	val64 = dev->mtu;
	writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);

	if (nic->device_type & XFRAME_II_DEVICE) {
		while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
			SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
					  &bar0->dtx_control, UF);
			if (dtx_cnt & 0x1)
				msleep(1); /* Necessary!! */
			dtx_cnt++;
		}
	} else {
		while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
			SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
					  &bar0->dtx_control, UF);
			val64 = readq(&bar0->dtx_control);
			dtx_cnt++;
		}
	}

	/*  Tx DMA Initialization */
	val64 = 0;
	writeq(val64, &bar0->tx_fifo_partition_0);
	writeq(val64, &bar0->tx_fifo_partition_1);
	writeq(val64, &bar0->tx_fifo_partition_2);
	writeq(val64, &bar0->tx_fifo_partition_3);


	for (i = 0, j = 0; i < config->tx_fifo_num; i++) {
		val64 |=
		    vBIT(config->tx_cfg[i].fifo_len - 1, ((i * 32) + 19),
			 13) | vBIT(config->tx_cfg[i].fifo_priority,
				    ((i * 32) + 5), 3);

		if (i == (config->tx_fifo_num - 1)) {
			if (i % 2 == 0)
				i++;
		}

		switch (i) {
		case 1:
			writeq(val64, &bar0->tx_fifo_partition_0);
			val64 = 0;
			break;
		case 3:
			writeq(val64, &bar0->tx_fifo_partition_1);
			val64 = 0;
			break;
		case 5:
			writeq(val64, &bar0->tx_fifo_partition_2);
			val64 = 0;
			break;
		case 7:
			writeq(val64, &bar0->tx_fifo_partition_3);
			break;
		}
	}

	/*
	 * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
	 * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
	 */
	if ((nic->device_type == XFRAME_I_DEVICE) &&
		(get_xena_rev_id(nic->pdev) < 4))
		writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);

	val64 = readq(&bar0->tx_fifo_partition_0);
	DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",
		  &bar0->tx_fifo_partition_0, (unsigned long long) val64);

	/*
	 * Initialization of Tx_PA_CONFIG register to ignore packet
	 * integrity checking.
	 */
	val64 = readq(&bar0->tx_pa_cfg);
	val64 |= TX_PA_CFG_IGNORE_FRM_ERR | TX_PA_CFG_IGNORE_SNAP_OUI |
	    TX_PA_CFG_IGNORE_LLC_CTRL | TX_PA_CFG_IGNORE_L2_ERR;
	writeq(val64, &bar0->tx_pa_cfg);

	/* Rx DMA intialization. */
	val64 = 0;
	for (i = 0; i < config->rx_ring_num; i++) {
		val64 |=
		    vBIT(config->rx_cfg[i].ring_priority, (5 + (i * 8)),
			 3);
	}
	writeq(val64, &bar0->rx_queue_priority);

	/*
	 * Allocating equal share of memory to all the
	 * configured Rings.
	 */
	val64 = 0;
	if (nic->device_type & XFRAME_II_DEVICE)
		mem_size = 32;
	else
		mem_size = 64;

	for (i = 0; i < config->rx_ring_num; i++) {
		switch (i) {
		case 0:
			mem_share = (mem_size / config->rx_ring_num +
				     mem_size % config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);
			continue;
		case 1:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);
			continue;
		case 2:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);
			continue;
		case 3:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);
			continue;
		case 4:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);
			continue;
		case 5:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);
			continue;
		case 6:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);
			continue;
		case 7:
			mem_share = (mem_size / config->rx_ring_num);
			val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);
			continue;
		}
	}
	writeq(val64, &bar0->rx_queue_cfg);

	/*
	 * Filling Tx round robin registers
	 * as per the number of FIFOs
	 */
	switch (config->tx_fifo_num) {
	case 1:
		val64 = 0x0000000000000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		writeq(val64, &bar0->tx_w_round_robin_1);
		writeq(val64, &bar0->tx_w_round_robin_2);
		writeq(val64, &bar0->tx_w_round_robin_3);
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 2:
		val64 = 0x0000010000010000ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0100000100000100ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0001000001000001ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0000010000010000ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0100000000000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 3:
		val64 = 0x0001000102000001ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0001020000010001ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0200000100010200ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0001000102000001ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0001020000000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 4:
		val64 = 0x0001020300010200ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0100000102030001ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0200010000010203ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0001020001000001ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0203000100000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 5:
		val64 = 0x0001000203000102ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0001020001030004ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0001000203000102ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0001020001030004ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0001000000000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 6:
		val64 = 0x0001020304000102ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0304050001020001ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0203000100000102ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0304000102030405ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0001000200000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 7:
		val64 = 0x0001020001020300ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0102030400010203ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0405060001020001ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0304050000010200ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0102030000000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	case 8:
		val64 = 0x0001020300040105ULL;
		writeq(val64, &bar0->tx_w_round_robin_0);
		val64 = 0x0200030106000204ULL;
		writeq(val64, &bar0->tx_w_round_robin_1);
		val64 = 0x0103000502010007ULL;
		writeq(val64, &bar0->tx_w_round_robin_2);
		val64 = 0x0304010002060500ULL;
		writeq(val64, &bar0->tx_w_round_robin_3);
		val64 = 0x0103020400000000ULL;
		writeq(val64, &bar0->tx_w_round_robin_4);
		break;
	}

	/* Enable all configured Tx FIFO partitions */
	val64 = readq(&bar0->tx_fifo_partition_0);
	val64 |= (TX_FIFO_PARTITION_EN);
	writeq(val64, &bar0->tx_fifo_partition_0);

	/* Filling the Rx round robin registers as per the
	 * number of Rings and steering based on QoS.
         */
	switch (config->rx_ring_num) {
	case 1:
		val64 = 0x8080808080808080ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 2:
		val64 = 0x0000010000010000ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0100000100000100ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0001000001000001ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0000010000010000ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0100000000000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080808040404040ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 3:
		val64 = 0x0001000102000001ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0001020000010001ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0200000100010200ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0001000102000001ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0001020000000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080804040402020ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 4:
		val64 = 0x0001020300010200ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0100000102030001ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0200010000010203ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0001020001000001ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0203000100000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080404020201010ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 5:
		val64 = 0x0001000203000102ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0001020001030004ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0001000203000102ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0001020001030004ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0001000000000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080404020201008ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 6:
		val64 = 0x0001020304000102ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0304050001020001ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0203000100000102ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0304000102030405ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0001000200000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080404020100804ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 7:
		val64 = 0x0001020001020300ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0102030400010203ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0405060001020001ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0304050000010200ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0102030000000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8080402010080402ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	case 8:
		val64 = 0x0001020300040105ULL;
		writeq(val64, &bar0->rx_w_round_robin_0);
		val64 = 0x0200030106000204ULL;
		writeq(val64, &bar0->rx_w_round_robin_1);
		val64 = 0x0103000502010007ULL;
		writeq(val64, &bar0->rx_w_round_robin_2);
		val64 = 0x0304010002060500ULL;
		writeq(val64, &bar0->rx_w_round_robin_3);
		val64 = 0x0103020400000000ULL;
		writeq(val64, &bar0->rx_w_round_robin_4);

		val64 = 0x8040201008040201ULL;
		writeq(val64, &bar0->rts_qos_steering);
		break;
	}

	/* UDP Fix */
	val64 = 0;
	for (i = 0; i < 8; i++)
		writeq(val64, &bar0->rts_frm_len_n[i]);

	/* Set the default rts frame length for the rings configured */
	val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22);
	for (i = 0 ; i < config->rx_ring_num ; i++)
		writeq(val64, &bar0->rts_frm_len_n[i]);

	/* Set the frame length for the configured rings
	 * desired by the user
	 */
	for (i = 0; i < config->rx_ring_num; i++) {
		/* If rts_frm_len[i] == 0 then it is assumed that user not
		 * specified frame length steering.
		 * If the user provides the frame length then program
		 * the rts_frm_len register for those values or else
		 * leave it as it is.
		 */
		if (rts_frm_len[i] != 0) {
			writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]),
				&bar0->rts_frm_len_n[i]);
		}
	}
	
	/* Disable differentiated services steering logic */
	for (i = 0; i < 64; i++) {
		if (rts_ds_steer(nic, i, 0) == FAILURE) {
			DBG_PRINT(ERR_DBG, "%s: failed rts ds steering",
				dev->name);
			DBG_PRINT(ERR_DBG, "set on codepoint %d\n", i);
			return FAILURE;
		}
	}

	/* Program statistics memory */
	writeq(mac_control->stats_mem_phy, &bar0->stat_addr);

	if (nic->device_type == XFRAME_II_DEVICE) {
		val64 = STAT_BC(0x320);
		writeq(val64, &bar0->stat_byte_cnt);
	}

	/*
	 * Initializing the sampling rate for the device to calculate the
	 * bandwidth utilization.
	 */
	val64 = MAC_TX_LINK_UTIL_VAL(tmac_util_period) |
	    MAC_RX_LINK_UTIL_VAL(rmac_util_period);
	writeq(val64, &bar0->mac_link_util);


	/*
	 * Initializing the Transmit and Receive Traffic Interrupt
	 * Scheme.
	 */
	/*
	 * TTI Initialization. Default Tx timer gets us about
	 * 250 interrupts per sec. Continuous interrupts are enabled
	 * by default.
	 */
	if (nic->device_type == XFRAME_II_DEVICE) {
		int count = (nic->config.bus_speed * 125)/2;
		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count);
	} else {

		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078);
	}
	val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |
	    TTI_DATA1_MEM_TX_URNG_B(0x10) |
	    TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN;
		if (use_continuous_tx_intrs)
			val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
	writeq(val64, &bar0->tti_data1_mem);

	val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
	    TTI_DATA2_MEM_TX_UFC_B(0x20) |
	    TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
	writeq(val64, &bar0->tti_data2_mem);

	val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
	writeq(val64, &bar0->tti_command_mem);

	/*
	 * Once the operation completes, the Strobe bit of the command
	 * register will be reset. We poll for this particular condition
	 * We wait for a maximum of 500ms for the operation to complete,
	 * if it's not complete by then we return error.
	 */
	time = 0;
	while (TRUE) {
		val64 = readq(&bar0->tti_command_mem);
		if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
			break;
		}
		if (time > 10) {
			DBG_PRINT(ERR_DBG, "%s: TTI init Failed\n",
				  dev->name);
			return -1;
		}
		msleep(50);
		time++;
	}

	if (nic->config.bimodal) {
		int k = 0;
		for (k = 0; k < config->rx_ring_num; k++) {
			val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
			val64 |= TTI_CMD_MEM_OFFSET(0x38+k);
			writeq(val64, &bar0->tti_command_mem);

		/*
		 * Once the operation completes, the Strobe bit of the command
		 * register will be reset. We poll for this particular condition
		 * We wait for a maximum of 500ms for the operation to complete,
		 * if it's not complete by then we return error.
		*/
			time = 0;
			while (TRUE) {
				val64 = readq(&bar0->tti_command_mem);
				if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) {
					break;
				}
				if (time > 10) {
					DBG_PRINT(ERR_DBG,
						"%s: TTI init Failed\n",
					dev->name);
					return -1;
				}
				time++;
				msleep(50);
			}
		}
	} else {

		/* RTI Initialization */
		if (nic->device_type == XFRAME_II_DEVICE) {
			/*
			 * Programmed to generate Apprx 500 Intrs per
			 * second
			 */
			int count = (nic->config.bus_speed * 125)/4;
			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count);
		} else {
			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF);
		}
		val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) |
		    RTI_DATA1_MEM_RX_URNG_B(0x10) |
		    RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN;

		writeq(val64, &bar0->rti_data1_mem);

		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
		    RTI_DATA2_MEM_RX_UFC_B(0x2) ;
		if (nic->intr_type == MSI_X)
		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
				RTI_DATA2_MEM_RX_UFC_D(0x40));
		else
		    val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
				RTI_DATA2_MEM_RX_UFC_D(0x80));
		writeq(val64, &bar0->rti_data2_mem);

		for (i = 0; i < config->rx_ring_num; i++) {
			val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD
					| RTI_CMD_MEM_OFFSET(i);
			writeq(val64, &bar0->rti_command_mem);

			/*
			 * Once the operation completes, the Strobe bit of the
			 * command register will be reset. We poll for this
			 * particular condition. We wait for a maximum of 500ms
			 * for the operation to complete, if it's not complete
			 * by then we return error.
			 */
			time = 0;
			while (TRUE) {
				val64 = readq(&bar0->rti_command_mem);
				if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) {
					break;
				}
				if (time > 10) {
					DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n",
						  dev->name);
					return -1;
				}
				time++;
				msleep(50);
			}
		}
	}

	/*
	 * Initializing proper values as Pause threshold into all
	 * the 8 Queues on Rx side.
	 */
	writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);
	writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);

	/* Disable RMAC PAD STRIPPING */
	add = &bar0->mac_cfg;
	val64 = readq(&bar0->mac_cfg);
	val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
	writel((u32) (val64), add);
	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
	writel((u32) (val64 >> 32), (add + 4));
	val64 = readq(&bar0->mac_cfg);

	/* Enable FCS stripping by adapter */
	add = &bar0->mac_cfg;
	val64 = readq(&bar0->mac_cfg);
	val64 |= MAC_CFG_RMAC_STRIP_FCS;
	if (nic->device_type == XFRAME_II_DEVICE)
		writeq(val64, &bar0->mac_cfg);
	else {
		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
		writel((u32) (val64), add);
		writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
		writel((u32) (val64 >> 32), (add + 4));
	}

	/*
	 * Set the time value to be inserted in the pause frame
	 * generated by xena.
	 */
	val64 = readq(&bar0->rmac_pause_cfg);
	val64 &= ~(RMAC_PAUSE_HG_PTIME(0xffff));
	val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);
	writeq(val64, &bar0->rmac_pause_cfg);

	/*
	 * Set the Threshold Limit for Generating the pause frame
	 * If the amount of data in any Queue exceeds ratio of
	 * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256
	 * pause frame is generated
	 */
	val64 = 0;
	for (i = 0; i < 4; i++) {
		val64 |=
		    (((u64) 0xFF00 | nic->mac_control.
		      mc_pause_threshold_q0q3)
		     << (i * 2 * 8));
	}
	writeq(val64, &bar0->mc_pause_thresh_q0q3);

	val64 = 0;
	for (i = 0; i < 4; i++) {
		val64 |=
		    (((u64) 0xFF00 | nic->mac_control.
		      mc_pause_threshold_q4q7)
		     << (i * 2 * 8));
	}
	writeq(val64, &bar0->mc_pause_thresh_q4q7);

	/*
	 * TxDMA will stop Read request if the number of read split has
	 * exceeded the limit pointed by shared_splits
	 */
	val64 = readq(&bar0->pic_control);
	val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
	writeq(val64, &bar0->pic_control);

	if (nic->config.bus_speed == 266) {
		writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout);
		writeq(0x0, &bar0->read_retry_delay);
		writeq(0x0, &bar0->write_retry_delay);
	}

	/*
	 * Programming the Herc to split every write transaction
	 * that does not start on an ADB to reduce disconnects.
	 */
	if (nic->device_type == XFRAME_II_DEVICE) {
		val64 = FAULT_BEHAVIOUR | EXT_REQ_EN |
			MISC_LINK_STABILITY_PRD(3);
		writeq(val64, &bar0->misc_control);
		val64 = readq(&bar0->pic_control2);
		val64 &= ~(BIT(13)|BIT(14)|BIT(15));
		writeq(val64, &bar0->pic_control2);
	}
	if (strstr(nic->product_name, "CX4")) {
		val64 = TMAC_AVG_IPG(0x17);
		writeq(val64, &bar0->tmac_avg_ipg);
	}

	return SUCCESS;
}
#define LINK_UP_DOWN_INTERRUPT		1
#define MAC_RMAC_ERR_TIMER		2

static int s2io_link_fault_indication(struct s2io_nic *nic)
{
	if (nic->intr_type != INTA)
		return MAC_RMAC_ERR_TIMER;
	if (nic->device_type == XFRAME_II_DEVICE)
		return LINK_UP_DOWN_INTERRUPT;
	else
		return MAC_RMAC_ERR_TIMER;
}

/**
 *  en_dis_able_nic_intrs - Enable or Disable the interrupts
 *  @nic: device private variable,
 *  @mask: A mask indicating which Intr block must be modified and,
 *  @flag: A flag indicating whether to enable or disable the Intrs.
 *  Description: This function will either disable or enable the interrupts
 *  depending on the flag argument. The mask argument can be used to
 *  enable/disable any Intr block.
 *  Return Value: NONE.
 */

static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	register u64 val64 = 0, temp64 = 0;

	/*  Top level interrupt classification */
	/*  PIC Interrupts */
	if ((mask & (TX_PIC_INTR | RX_PIC_INTR))) {
		/*  Enable PIC Intrs in the general intr mask register */
		val64 = TXPIC_INT_M;
		if (flag == ENABLE_INTRS) {
			temp64 = readq(&bar0->general_int_mask);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->general_int_mask);
			/*
			 * If Hercules adapter enable GPIO otherwise
			 * disable all PCIX, Flash, MDIO, IIC and GPIO
			 * interrupts for now.
			 * TODO
			 */
			if (s2io_link_fault_indication(nic) ==
					LINK_UP_DOWN_INTERRUPT ) {
				temp64 = readq(&bar0->pic_int_mask);
				temp64 &= ~((u64) PIC_INT_GPIO);
				writeq(temp64, &bar0->pic_int_mask);
				temp64 = readq(&bar0->gpio_int_mask);
				temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP);
				writeq(temp64, &bar0->gpio_int_mask);
			} else {
				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
			}
			/*
			 * No MSI Support is available presently, so TTI and
			 * RTI interrupts are also disabled.
			 */
		} else if (flag == DISABLE_INTRS) {
			/*
			 * Disable PIC Intrs in the general
			 * intr mask register
			 */
			writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);
			temp64 = readq(&bar0->general_int_mask);
			val64 |= temp64;
			writeq(val64, &bar0->general_int_mask);
		}
	}

	/*  MAC Interrupts */
	/*  Enabling/Disabling MAC interrupts */
	if (mask & (TX_MAC_INTR | RX_MAC_INTR)) {
		val64 = TXMAC_INT_M | RXMAC_INT_M;
		if (flag == ENABLE_INTRS) {
			temp64 = readq(&bar0->general_int_mask);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->general_int_mask);
			/*
			 * All MAC block error interrupts are disabled for now
			 * TODO
			 */
		} else if (flag == DISABLE_INTRS) {
			/*
			 * Disable MAC Intrs in the general intr mask register
			 */
			writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);
			writeq(DISABLE_ALL_INTRS,
			       &bar0->mac_rmac_err_mask);

			temp64 = readq(&bar0->general_int_mask);
			val64 |= temp64;
			writeq(val64, &bar0->general_int_mask);
		}
	}

	/*  Tx traffic interrupts */
	if (mask & TX_TRAFFIC_INTR) {
		val64 = TXTRAFFIC_INT_M;
		if (flag == ENABLE_INTRS) {
			temp64 = readq(&bar0->general_int_mask);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->general_int_mask);
			/*
			 * Enable all the Tx side interrupts
			 * writing 0 Enables all 64 TX interrupt levels
			 */
			writeq(0x0, &bar0->tx_traffic_mask);
		} else if (flag == DISABLE_INTRS) {
			/*
			 * Disable Tx Traffic Intrs in the general intr mask
			 * register.
			 */
			writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask);
			temp64 = readq(&bar0->general_int_mask);
			val64 |= temp64;
			writeq(val64, &bar0->general_int_mask);
		}
	}

	/*  Rx traffic interrupts */
	if (mask & RX_TRAFFIC_INTR) {
		val64 = RXTRAFFIC_INT_M;
		if (flag == ENABLE_INTRS) {
			temp64 = readq(&bar0->general_int_mask);
			temp64 &= ~((u64) val64);
			writeq(temp64, &bar0->general_int_mask);
			/* writing 0 Enables all 8 RX interrupt levels */
			writeq(0x0, &bar0->rx_traffic_mask);
		} else if (flag == DISABLE_INTRS) {
			/*
			 * Disable Rx Traffic Intrs in the general intr mask
			 * register.
			 */
			writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask);
			temp64 = readq(&bar0->general_int_mask);
			val64 |= temp64;
			writeq(val64, &bar0->general_int_mask);
		}
	}
}

/**
 *  verify_pcc_quiescent- Checks for PCC quiescent state
 *  Return: 1 If PCC is quiescence
 *          0 If PCC is not quiescence
 */
static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
{
	int ret = 0, herc;
	struct XENA_dev_config __iomem *bar0 = sp->bar0;
	u64 val64 = readq(&bar0->adapter_status);
	
	herc = (sp->device_type == XFRAME_II_DEVICE);

	if (flag == FALSE) {
		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
				ret = 1;
		} else {
			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE))
				ret = 1;
		}
	} else {
		if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
			if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
			     ADAPTER_STATUS_RMAC_PCC_IDLE))
				ret = 1;
		} else {
			if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) ==
			     ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE))
				ret = 1;
		}
	}

	return ret;
}
/**
 *  verify_xena_quiescence - Checks whether the H/W is ready
 *  Description: Returns whether the H/W is ready to go or not. Depending
 *  on whether adapter enable bit was written or not the comparison
 *  differs and the calling function passes the input argument flag to
 *  indicate this.
 *  Return: 1 If xena is quiescence
 *          0 If Xena is not quiescence
 */

static int verify_xena_quiescence(struct s2io_nic *sp)
{
	int  mode;
	struct XENA_dev_config __iomem *bar0 = sp->bar0;
	u64 val64 = readq(&bar0->adapter_status);
	mode = s2io_verify_pci_mode(sp);

	if (!(val64 & ADAPTER_STATUS_TDMA_READY)) {
		DBG_PRINT(ERR_DBG, "%s", "TDMA is not ready!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_RDMA_READY)) {
	DBG_PRINT(ERR_DBG, "%s", "RDMA is not ready!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_PFC_READY)) {
		DBG_PRINT(ERR_DBG, "%s", "PFC is not ready!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_TMAC_BUF_EMPTY)) {
		DBG_PRINT(ERR_DBG, "%s", "TMAC BUF is not empty!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_PIC_QUIESCENT)) {
		DBG_PRINT(ERR_DBG, "%s", "PIC is not QUIESCENT!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_MC_DRAM_READY)) {
		DBG_PRINT(ERR_DBG, "%s", "MC_DRAM is not ready!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_MC_QUEUES_READY)) {
		DBG_PRINT(ERR_DBG, "%s", "MC_QUEUES is not ready!");
		return 0;
	}
	if (!(val64 & ADAPTER_STATUS_M_PLL_LOCK)) {
		DBG_PRINT(ERR_DBG, "%s", "M_PLL is not locked!");
		return 0;
	}

	/*
	 * In PCI 33 mode, the P_PLL is not used, and therefore,
	 * the the P_PLL_LOCK bit in the adapter_status register will
	 * not be asserted.
	 */
	if (!(val64 & ADAPTER_STATUS_P_PLL_LOCK) &&
		sp->device_type == XFRAME_II_DEVICE && mode !=
		PCI_MODE_PCI_33) {
		DBG_PRINT(ERR_DBG, "%s", "P_PLL is not locked!");
		return 0;
	}
	if (!((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) ==
			ADAPTER_STATUS_RC_PRC_QUIESCENT)) {
		DBG_PRINT(ERR_DBG, "%s", "RC_PRC is not QUIESCENT!");
		return 0;
	}
	return 1;
}

/**
 * fix_mac_address -  Fix for Mac addr problem on Alpha platforms
 * @sp: Pointer to device specifc structure
 * Description :
 * New procedure to clear mac address reading  problems on Alpha platforms
 *
 */

static void fix_mac_address(struct s2io_nic * sp)
{
	struct XENA_dev_config __iomem *bar0 = sp->bar0;
	u64 val64;
	int i = 0;

	while (fix_mac[i] != END_SIGN) {
		writeq(fix_mac[i++], &bar0->gpio_control);
		udelay(10);
		val64 = readq(&bar0->gpio_control);
	}
}

/**
 *  start_nic - Turns the device on
 *  @nic : device private variable.
 *  Description:
 *  This function actually turns the device on. Before this  function is
 *  called,all Registers are configured from their reset states
 *  and shared memory is allocated but the NIC is still quiescent. On
 *  calling this function, the device interrupts are cleared and the NIC is
 *  literally switched on by writing into the adapter control register.
 *  Return Value:
 *  SUCCESS on success and -1 on failure.
 */

static int start_nic(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	struct net_device *dev = nic->dev;
	register u64 val64 = 0;
	u16 subid, i;
	struct mac_info *mac_control;
	struct config_param *config;

	mac_control = &nic->mac_control;
	config = &nic->config;

	/*  PRC Initialization and configuration */
	for (i = 0; i < config->rx_ring_num; i++) {
		writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,
		       &bar0->prc_rxd0_n[i]);

		val64 = readq(&bar0->prc_ctrl_n[i]);
		if (nic->config.bimodal)
			val64 |= PRC_CTRL_BIMODAL_INTERRUPT;
		if (nic->rxd_mode == RXD_MODE_1)
			val64 |= PRC_CTRL_RC_ENABLED;
		else
			val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
		if (nic->device_type == XFRAME_II_DEVICE)
			val64 |= PRC_CTRL_GROUP_READS;
		val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF);
		val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000);
		writeq(val64, &bar0->prc_ctrl_n[i]);
	}

	if (nic->rxd_mode == RXD_MODE_3B) {
		/* Enabling 2 buffer mode by writing into Rx_pa_cfg reg. */
		val64 = readq(&bar0->rx_pa_cfg);
		val64 |= RX_PA_CFG_IGNORE_L2_ERR;
		writeq(val64, &bar0->rx_pa_cfg);
	}

	if (vlan_tag_strip == 0) {
		val64 = readq(&bar0->rx_pa_cfg);
		val64 &= ~RX_PA_CFG_STRIP_VLAN_TAG;
		writeq(val64, &bar0->rx_pa_cfg);
		vlan_strip_flag = 0;
	}

	/*
	 * Enabling MC-RLDRAM. After enabling the device, we timeout
	 * for around 100ms, which is approximately the time required
	 * for the device to be ready for operation.
	 */
	val64 = readq(&bar0->mc_rldram_mrs);
	val64 |= MC_RLDRAM_QUEUE_SIZE_ENABLE | MC_RLDRAM_MRS_ENABLE;
	SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
	val64 = readq(&bar0->mc_rldram_mrs);

	msleep(100);	/* Delay by around 100 ms. */

	/* Enabling ECC Protection. */
	val64 = readq(&bar0->adapter_control);
	val64 &= ~ADAPTER_ECC_EN;
	writeq(val64, &bar0->adapter_control);

	/*
	 * Clearing any possible Link state change interrupts that
	 * could have popped up just before Enabling the card.
	 */
	val64 = readq(&bar0->mac_rmac_err_reg);
	if (val64)
		writeq(val64, &bar0->mac_rmac_err_reg);

	/*
	 * Verify if the device is ready to be enabled, if so enable
	 * it.
	 */
	val64 = readq(&bar0->adapter_status);
	if (!verify_xena_quiescence(nic)) {
		DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);
		DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",
			  (unsigned long long) val64);
		return FAILURE;
	}

	/*
	 * With some switches, link might be already up at this point.
	 * Because of this weird behavior, when we enable laser,
	 * we may not get link. We need to handle this. We cannot
	 * figure out which switch is misbehaving. So we are forced to
	 * make a global change.
	 */

	/* Enabling Laser. */
	val64 = readq(&bar0->adapter_control);
	val64 |= ADAPTER_EOI_TX_ON;
	writeq(val64, &bar0->adapter_control);

	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
		/*
		 * Dont see link state interrupts initally on some switches,
		 * so directly scheduling the link state task here.
		 */
		schedule_work(&nic->set_link_task);
	}
	/* SXE-002: Initialize link and activity LED */
	subid = nic->pdev->subsystem_device;
	if (((subid & 0xFF) >= 0x07) &&
	    (nic->device_type == XFRAME_I_DEVICE)) {
		val64 = readq(&bar0->gpio_control);
		val64 |= 0x0000800000000000ULL;
		writeq(val64, &bar0->gpio_control);
		val64 = 0x0411040400000000ULL;
		writeq(val64, (void __iomem *)bar0 + 0x2700);
	}

	return SUCCESS;
}
/**
 * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb
 */
static struct sk_buff *s2io_txdl_getskb(struct fifo_info *fifo_data, struct \
					TxD *txdlp, int get_off)
{
	struct s2io_nic *nic = fifo_data->nic;
	struct sk_buff *skb;
	struct TxD *txds;
	u16 j, frg_cnt;

	txds = txdlp;
	if (txds->Host_Control == (u64)(long)nic->ufo_in_band_v) {
		pci_unmap_single(nic->pdev, (dma_addr_t)
			txds->Buffer_Pointer, sizeof(u64),
			PCI_DMA_TODEVICE);
		txds++;
	}

	skb = (struct sk_buff *) ((unsigned long)
			txds->Host_Control);
	if (!skb) {
		memset(txdlp, 0, (sizeof(struct TxD) * fifo_data->max_txds));
		return NULL;
	}
	pci_unmap_single(nic->pdev, (dma_addr_t)
			 txds->Buffer_Pointer,
			 skb->len - skb->data_len,
			 PCI_DMA_TODEVICE);
	frg_cnt = skb_shinfo(skb)->nr_frags;
	if (frg_cnt) {
		txds++;
		for (j = 0; j < frg_cnt; j++, txds++) {
			skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
			if (!txds->Buffer_Pointer)
				break;
			pci_unmap_page(nic->pdev, (dma_addr_t)
					txds->Buffer_Pointer,
				       frag->size, PCI_DMA_TODEVICE);
		}
	}
	memset(txdlp,0, (sizeof(struct TxD) * fifo_data->max_txds));
	return(skb);
}

/**
 *  free_tx_buffers - Free all queued Tx buffers
 *  @nic : device private variable.
 *  Description:
 *  Free all queued Tx buffers.
 *  Return Value: void
*/

static void free_tx_buffers(struct s2io_nic *nic)
{
	struct net_device *dev = nic->dev;
	struct sk_buff *skb;
	struct TxD *txdp;
	int i, j;
	struct mac_info *mac_control;
	struct config_param *config;
	int cnt = 0;

	mac_control = &nic->mac_control;
	config = &nic->config;

	for (i = 0; i < config->tx_fifo_num; i++) {
		for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) {
			txdp = (struct TxD *) mac_control->fifos[i].list_info[j].
			    list_virt_addr;
			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
			if (skb) {
				dev_kfree_skb(skb);
				cnt++;
			}
		}
		DBG_PRINT(INTR_DBG,
			  "%s:forcibly freeing %d skbs on FIFO%d\n",
			  dev->name, cnt, i);
		mac_control->fifos[i].tx_curr_get_info.offset = 0;
		mac_control->fifos[i].tx_curr_put_info.offset = 0;
	}
}

/**
 *   stop_nic -  To stop the nic
 *   @nic ; device private variable.
 *   Description:
 *   This function does exactly the opposite of what the start_nic()
 *   function does. This function is called to stop the device.
 *   Return Value:
 *   void.
 */

static void stop_nic(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	register u64 val64 = 0;
	u16 interruptible;
	struct mac_info *mac_control;
	struct config_param *config;

	mac_control = &nic->mac_control;
	config = &nic->config;

	/*  Disable all interrupts */
	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
	interruptible |= TX_PIC_INTR | RX_PIC_INTR;
	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);

	/* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
	val64 = readq(&bar0->adapter_control);
	val64 &= ~(ADAPTER_CNTL_EN);
	writeq(val64, &bar0->adapter_control);
}

static int fill_rxd_3buf(struct s2io_nic *nic, struct RxD_t *rxdp, struct \
				sk_buff *skb)
{
	struct net_device *dev = nic->dev;
	struct sk_buff *frag_list;
	void *tmp;

	/* Buffer-1 receives L3/L4 headers */
	((struct RxD3*)rxdp)->Buffer1_ptr = pci_map_single
			(nic->pdev, skb->data, l3l4hdr_size + 4,
			PCI_DMA_FROMDEVICE);

	/* skb_shinfo(skb)->frag_list will have L4 data payload */
	skb_shinfo(skb)->frag_list = dev_alloc_skb(dev->mtu + ALIGN_SIZE);
	if (skb_shinfo(skb)->frag_list == NULL) {
		DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n ", dev->name);
		return -ENOMEM ;
	}
	frag_list = skb_shinfo(skb)->frag_list;
	skb->truesize += frag_list->truesize;
	frag_list->next = NULL;
	tmp = (void *)ALIGN((long)frag_list->data, ALIGN_SIZE + 1);
	frag_list->data = tmp;
	frag_list->tail = tmp;

	/* Buffer-2 receives L4 data payload */
	((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single(nic->pdev,
				frag_list->data, dev->mtu,
				PCI_DMA_FROMDEVICE);
	rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4);
	rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu);

	return SUCCESS;
}

/**
 *  fill_rx_buffers - Allocates the Rx side skbs
 *  @nic:  device private variable
 *  @ring_no: ring number
 *  Description:
 *  The function allocates Rx side skbs and puts the physical
 *  address of these buffers into the RxD buffer pointers, so that the NIC
 *  can DMA the received frame into these locations.
 *  The NIC supports 3 receive modes, viz
 *  1. single buffer,
 *  2. three buffer and
 *  3. Five buffer modes.
 *  Each mode defines how many fragments the received frame will be split
 *  up into by the NIC. The frame is split into L3 header, L4 Header,
 *  L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself
 *  is split into 3 fragments. As of now only single buffer mode is
 *  supported.
 *   Return Value:
 *  SUCCESS on success or an appropriate -ve value on failure.
 */

static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
{
	struct net_device *dev = nic->dev;
	struct sk_buff *skb;
	struct RxD_t *rxdp;
	int off, off1, size, block_no, block_no1;
	u32 alloc_tab = 0;
	u32 alloc_cnt;
	struct mac_info *mac_control;
	struct config_param *config;
	u64 tmp;
	struct buffAdd *ba;
	unsigned long flags;
	struct RxD_t *first_rxdp = NULL;

	mac_control = &nic->mac_control;
	config = &nic->config;
	alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
	    atomic_read(&nic->rx_bufs_left[ring_no]);

	block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
	off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
	while (alloc_tab < alloc_cnt) {
		block_no = mac_control->rings[ring_no].rx_curr_put_info.
		    block_index;
		off = mac_control->rings[ring_no].rx_curr_put_info.offset;

		rxdp = mac_control->rings[ring_no].
				rx_blocks[block_no].rxds[off].virt_addr;

		if ((block_no == block_no1) && (off == off1) &&
					(rxdp->Host_Control)) {
			DBG_PRINT(INTR_DBG, "%s: Get and Put",
				  dev->name);
			DBG_PRINT(INTR_DBG, " info equated\n");
			goto end;
		}
		if (off && (off == rxd_count[nic->rxd_mode])) {
			mac_control->rings[ring_no].rx_curr_put_info.
			    block_index++;
			if (mac_control->rings[ring_no].rx_curr_put_info.
			    block_index == mac_control->rings[ring_no].
					block_count)
				mac_control->rings[ring_no].rx_curr_put_info.
					block_index = 0;
			block_no = mac_control->rings[ring_no].
					rx_curr_put_info.block_index;
			if (off == rxd_count[nic->rxd_mode])
				off = 0;
			mac_control->rings[ring_no].rx_curr_put_info.
				offset = off;
			rxdp = mac_control->rings[ring_no].
				rx_blocks[block_no].block_virt_addr;
			DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n",
				  dev->name, rxdp);
		}
		if(!napi) {
			spin_lock_irqsave(&nic->put_lock, flags);
			mac_control->rings[ring_no].put_pos =
			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
			spin_unlock_irqrestore(&nic->put_lock, flags);
		} else {
			mac_control->rings[ring_no].put_pos =
			(block_no * (rxd_count[nic->rxd_mode] + 1)) + off;
		}
		if ((rxdp->Control_1 & RXD_OWN_XENA) &&
			((nic->rxd_mode >= RXD_MODE_3A) &&
				(rxdp->Control_2 & BIT(0)))) {
			mac_control->rings[ring_no].rx_curr_put_info.
					offset = off;
			goto end;
		}
		/* calculate size of skb based on ring mode */
		size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
				HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
		if (nic->rxd_mode == RXD_MODE_1)
			size += NET_IP_ALIGN;
		else if (nic->rxd_mode == RXD_MODE_3B)
			size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
		else
			size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4;

		/* allocate skb */
		skb = dev_alloc_skb(size);
		if(!skb) {
			DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
			DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
			if (first_rxdp) {
				wmb();
				first_rxdp->Control_1 |= RXD_OWN_XENA;
			}
			return -ENOMEM ;
		}
		if (nic->rxd_mode == RXD_MODE_1) {
			/* 1 buffer mode - normal operation mode */
			memset(rxdp, 0, sizeof(struct RxD1));
			skb_reserve(skb, NET_IP_ALIGN);
			((struct RxD1*)rxdp)->Buffer0_ptr = pci_map_single
			    (nic->pdev, skb->data, size - NET_IP_ALIGN,
				PCI_DMA_FROMDEVICE);
			rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);

		} else if (nic->rxd_mode >= RXD_MODE_3A) {
			/*
			 * 2 or 3 buffer mode -
			 * Both 2 buffer mode and 3 buffer mode provides 128
			 * byte aligned receive buffers.
			 *
			 * 3 buffer mode provides header separation where in
			 * skb->data will have L3/L4 headers where as
			 * skb_shinfo(skb)->frag_list will have the L4 data
			 * payload
			 */

			memset(rxdp, 0, sizeof(struct RxD3));
			ba = &mac_control->rings[ring_no].ba[block_no][off];
			skb_reserve(skb, BUF0_LEN);
			tmp = (u64)(unsigned long) skb->data;
			tmp += ALIGN_SIZE;
			tmp &= ~ALIGN_SIZE;
			skb->data = (void *) (unsigned long)tmp;
			skb->tail = (void *) (unsigned long)tmp;

			if (!(((struct RxD3*)rxdp)->Buffer0_ptr))
				((struct RxD3*)rxdp)->Buffer0_ptr =
				   pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
					   PCI_DMA_FROMDEVICE);
			else
				pci_dma_sync_single_for_device(nic->pdev,
				    (dma_addr_t) ((struct RxD3*)rxdp)->Buffer0_ptr,
				    BUF0_LEN, PCI_DMA_FROMDEVICE);
			rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
			if (nic->rxd_mode == RXD_MODE_3B) {
				/* Two buffer mode */

				/*
				 * Buffer2 will have L3/L4 header plus
				 * L4 payload
				 */
				((struct RxD3*)rxdp)->Buffer2_ptr = pci_map_single
				(nic->pdev, skb->data, dev->mtu + 4,
						PCI_DMA_FROMDEVICE);

				/* Buffer-1 will be dummy buffer. Not used */
				if (!(((struct RxD3*)rxdp)->Buffer1_ptr)) {
					((struct RxD3*)rxdp)->Buffer1_ptr =
						pci_map_single(nic->pdev,
						ba->ba_1, BUF1_LEN,
						PCI_DMA_FROMDEVICE);
				}
				rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
				rxdp->Control_2 |= SET_BUFFER2_SIZE_3
								(dev->mtu + 4);
			} else {
				/* 3 buffer mode */
				if (fill_rxd_3buf(nic, rxdp, skb) == -ENOMEM) {
					dev_kfree_skb_irq(skb);
					if (first_rxdp) {
						wmb();
						first_rxdp->Control_1 |=
							RXD_OWN_XENA;
					}
					return -ENOMEM ;
				}
			}
			rxdp->Control_2 |= BIT(0);
		}
		rxdp->Host_Control = (unsigned long) (skb);
		if (alloc_tab & ((1 << rxsync_frequency) - 1))
			rxdp->Control_1 |= RXD_OWN_XENA;
		off++;
		if (off == (rxd_count[nic->rxd_mode] + 1))
			off = 0;
		mac_control->rings[ring_no].rx_curr_put_info.offset = off;

		rxdp->Control_2 |= SET_RXD_MARKER;
		if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) {
			if (first_rxdp) {
				wmb();
				first_rxdp->Control_1 |= RXD_OWN_XENA;
			}
			first_rxdp = rxdp;
		}
		atomic_inc(&nic->rx_bufs_left[ring_no]);
		alloc_tab++;
	}

      end:
	/* Transfer ownership of first descriptor to adapter just before
	 * exiting. Before that, use memory barrier so that ownership
	 * and other fields are seen by adapter correctly.
	 */
	if (first_rxdp) {
		wmb();
		first_rxdp->Control_1 |= RXD_OWN_XENA;
	}

	return SUCCESS;
}

static void free_rxd_blk(struct s2io_nic *sp, int ring_no, int blk)
{
	struct net_device *dev = sp->dev;
	int j;
	struct sk_buff *skb;
	struct RxD_t *rxdp;
	struct mac_info *mac_control;
	struct buffAdd *ba;

	mac_control = &sp->mac_control;
	for (j = 0 ; j < rxd_count[sp->rxd_mode]; j++) {
		rxdp = mac_control->rings[ring_no].
                                rx_blocks[blk].rxds[j].virt_addr;
		skb = (struct sk_buff *)
			((unsigned long) rxdp->Host_Control);
		if (!skb) {
			continue;
		}
		if (sp->rxd_mode == RXD_MODE_1) {
			pci_unmap_single(sp->pdev, (dma_addr_t)
				 ((struct RxD1*)rxdp)->Buffer0_ptr,
				 dev->mtu +
				 HEADER_ETHERNET_II_802_3_SIZE
				 + HEADER_802_2_SIZE +
				 HEADER_SNAP_SIZE,
				 PCI_DMA_FROMDEVICE);
			memset(rxdp, 0, sizeof(struct RxD1));
		} else if(sp->rxd_mode == RXD_MODE_3B) {
			ba = &mac_control->rings[ring_no].
				ba[blk][j];
			pci_unmap_single(sp->pdev, (dma_addr_t)
				 ((struct RxD3*)rxdp)->Buffer0_ptr,
				 BUF0_LEN,
				 PCI_DMA_FROMDEVICE);
			pci_unmap_single(sp->pdev, (dma_addr_t)
				 ((struct RxD3*)rxdp)->Buffer1_ptr,
				 BUF1_LEN,
				 PCI_DMA_FROMDEVICE);
			pci_unmap_single(sp->pdev, (dma_addr_t)
				 ((struct RxD3*)rxdp)->Buffer2_ptr,
				 dev->mtu + 4,
				 PCI_DMA_FROMDEVICE);
			memset(rxdp, 0, sizeof(struct RxD3));
		} else {
			pci_unmap_single(sp->pdev, (dma_addr_t)
				((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN,
				PCI_DMA_FROMDEVICE);
			pci_unmap_single(sp->pdev, (dma_addr_t)
				((struct RxD3*)rxdp)->Buffer1_ptr,
				l3l4hdr_size + 4,
				PCI_DMA_FROMDEVICE);
			pci_unmap_single(sp->pdev, (dma_addr_t)
				((struct RxD3*)rxdp)->Buffer2_ptr, dev->mtu,
				PCI_DMA_FROMDEVICE);
			memset(rxdp, 0, sizeof(struct RxD3));
		}
		dev_kfree_skb(skb);
		atomic_dec(&sp->rx_bufs_left[ring_no]);
	}
}

/**
 *  free_rx_buffers - Frees all Rx buffers
 *  @sp: device private variable.
 *  Description:
 *  This function will free all Rx buffers allocated by host.
 *  Return Value:
 *  NONE.
 */

static void free_rx_buffers(struct s2io_nic *sp)
{
	struct net_device *dev = sp->dev;
	int i, blk = 0, buf_cnt = 0;
	struct mac_info *mac_control;
	struct config_param *config;

	mac_control = &sp->mac_control;
	config = &sp->config;

	for (i = 0; i < config->rx_ring_num; i++) {
		for (blk = 0; blk < rx_ring_sz[i]; blk++)
			free_rxd_blk(sp,i,blk);

		mac_control->rings[i].rx_curr_put_info.block_index = 0;
		mac_control->rings[i].rx_curr_get_info.block_index = 0;
		mac_control->rings[i].rx_curr_put_info.offset = 0;
		mac_control->rings[i].rx_curr_get_info.offset = 0;
		atomic_set(&sp->rx_bufs_left[i], 0);
		DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",
			  dev->name, buf_cnt, i);
	}
}

/**
 * s2io_poll - Rx interrupt handler for NAPI support
 * @dev : pointer to the device structure.
 * @budget : The number of packets that were budgeted to be processed
 * during  one pass through the 'Poll" function.
 * Description:
 * Comes into picture only if NAPI support has been incorporated. It does
 * the same thing that rx_intr_handler does, but not in a interrupt context
 * also It will process only a given number of packets.
 * Return value:
 * 0 on success and 1 if there are No Rx packets to be processed.
 */

static int s2io_poll(struct net_device *dev, int *budget)
{
	struct s2io_nic *nic = dev->priv;
	int pkt_cnt = 0, org_pkts_to_process;
	struct mac_info *mac_control;
	struct config_param *config;
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	int i;

	atomic_inc(&nic->isr_cnt);
	mac_control = &nic->mac_control;
	config = &nic->config;

	nic->pkts_to_process = *budget;
	if (nic->pkts_to_process > dev->quota)
		nic->pkts_to_process = dev->quota;
	org_pkts_to_process = nic->pkts_to_process;

	writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
	readl(&bar0->rx_traffic_int);

	for (i = 0; i < config->rx_ring_num; i++) {
		rx_intr_handler(&mac_control->rings[i]);
		pkt_cnt = org_pkts_to_process - nic->pkts_to_process;
		if (!nic->pkts_to_process) {
			/* Quota for the current iteration has been met */
			goto no_rx;
		}
	}
	if (!pkt_cnt)
		pkt_cnt = 1;

	dev->quota -= pkt_cnt;
	*budget -= pkt_cnt;
	netif_rx_complete(dev);

	for (i = 0; i < config->rx_ring_num; i++) {
		if (fill_rx_buffers(nic, i) == -ENOMEM) {
			DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
			DBG_PRINT(ERR_DBG, " in Rx Poll!!\n");
			break;
		}
	}
	/* Re enable the Rx interrupts. */
	writeq(0x0, &bar0->rx_traffic_mask);
	readl(&bar0->rx_traffic_mask);
	atomic_dec(&nic->isr_cnt);
	return 0;

no_rx:
	dev->quota -= pkt_cnt;
	*budget -= pkt_cnt;

	for (i = 0; i < config->rx_ring_num; i++) {
		if (fill_rx_buffers(nic, i) == -ENOMEM) {
			DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
			DBG_PRINT(ERR_DBG, " in Rx Poll!!\n");
			break;
		}
	}
	atomic_dec(&nic->isr_cnt);
	return 1;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
/**
 * s2io_netpoll - netpoll event handler entry point
 * @dev : pointer to the device structure.
 * Description:
 * 	This function will be called by upper layer to check for events on the
 * interface in situations where interrupts are disabled. It is used for
 * specific in-kernel networking tasks, such as remote consoles and kernel
 * debugging over the network (example netdump in RedHat).
 */
static void s2io_netpoll(struct net_device *dev)
{
	struct s2io_nic *nic = dev->priv;
	struct mac_info *mac_control;
	struct config_param *config;
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
	int i;

	disable_irq(dev->irq);

	atomic_inc(&nic->isr_cnt);
	mac_control = &nic->mac_control;
	config = &nic->config;

	writeq(val64, &bar0->rx_traffic_int);
	writeq(val64, &bar0->tx_traffic_int);

	/* we need to free up the transmitted skbufs or else netpoll will
	 * run out of skbs and will fail and eventually netpoll application such
	 * as netdump will fail.
	 */
	for (i = 0; i < config->tx_fifo_num; i++)
		tx_intr_handler(&mac_control->fifos[i]);

	/* check for received packet and indicate up to network */
	for (i = 0; i < config->rx_ring_num; i++)
		rx_intr_handler(&mac_control->rings[i]);

	for (i = 0; i < config->rx_ring_num; i++) {
		if (fill_rx_buffers(nic, i) == -ENOMEM) {
			DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
			DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n");
			break;
		}
	}
	atomic_dec(&nic->isr_cnt);
	enable_irq(dev->irq);
	return;
}
#endif

/**
 *  rx_intr_handler - Rx interrupt handler
 *  @nic: device private variable.
 *  Description:
 *  If the interrupt is because of a received frame or if the
 *  receive ring contains fresh as yet un-processed frames,this function is
 *  called. It picks out the RxD at which place the last Rx processing had
 *  stopped and sends the skb to the OSM's Rx handler and then increments
 *  the offset.
 *  Return Value:
 *  NONE.
 */
static void rx_intr_handler(struct ring_info *ring_data)
{
	struct s2io_nic *nic = ring_data->nic;
	struct net_device *dev = (struct net_device *) nic->dev;
	int get_block, put_block, put_offset;
	struct rx_curr_get_info get_info, put_info;
	struct RxD_t *rxdp;
	struct sk_buff *skb;
	int pkt_cnt = 0;
	int i;

	spin_lock(&nic->rx_lock);
	if (atomic_read(&nic->card_state) == CARD_DOWN) {
		DBG_PRINT(INTR_DBG, "%s: %s going down for reset\n",
			  __FUNCTION__, dev->name);
		spin_unlock(&nic->rx_lock);
		return;
	}

	get_info = ring_data->rx_curr_get_info;
	get_block = get_info.block_index;
	memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info));
	put_block = put_info.block_index;
	rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr;
	if (!napi) {
		spin_lock(&nic->put_lock);
		put_offset = ring_data->put_pos;
		spin_unlock(&nic->put_lock);
	} else
		put_offset = ring_data->put_pos;

	while (RXD_IS_UP2DT(rxdp)) {
		/*
		 * If your are next to put index then it's
		 * FIFO full condition
		 */
		if ((get_block == put_block) &&
		    (get_info.offset + 1) == put_info.offset) {
			DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
			break;
		}
		skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
		if (skb == NULL) {
			DBG_PRINT(ERR_DBG, "%s: The skb is ",
				  dev->name);
			DBG_PRINT(ERR_DBG, "Null in Rx Intr\n");
			spin_unlock(&nic->rx_lock);
			return;
		}
		if (nic->rxd_mode == RXD_MODE_1) {
			pci_unmap_single(nic->pdev, (dma_addr_t)
				 ((struct RxD1*)rxdp)->Buffer0_ptr,
				 dev->mtu +
				 HEADER_ETHERNET_II_802_3_SIZE +
				 HEADER_802_2_SIZE +
				 HEADER_SNAP_SIZE,
				 PCI_DMA_FROMDEVICE);
		} else if (nic->rxd_mode == RXD_MODE_3B) {
			pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
				 ((struct RxD3*)rxdp)->Buffer0_ptr,
				 BUF0_LEN, PCI_DMA_FROMDEVICE);
			pci_unmap_single(nic->pdev, (dma_addr_t)
				 ((struct RxD3*)rxdp)->Buffer2_ptr,
				 dev->mtu + 4,
				 PCI_DMA_FROMDEVICE);
		} else {
			pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
					 ((struct RxD3*)rxdp)->Buffer0_ptr, BUF0_LEN,
					 PCI_DMA_FROMDEVICE);
			pci_unmap_single(nic->pdev, (dma_addr_t)
					 ((struct RxD3*)rxdp)->Buffer1_ptr,
					 l3l4hdr_size + 4,
					 PCI_DMA_FROMDEVICE);
			pci_unmap_single(nic->pdev, (dma_addr_t)
					 ((struct RxD3*)rxdp)->Buffer2_ptr,
					 dev->mtu, PCI_DMA_FROMDEVICE);
		}
		prefetch(skb->data);
		rx_osm_handler(ring_data, rxdp);
		get_info.offset++;
		ring_data->rx_curr_get_info.offset = get_info.offset;
		rxdp = ring_data->rx_blocks[get_block].
				rxds[get_info.offset].virt_addr;
		if (get_info.offset == rxd_count[nic->rxd_mode]) {
			get_info.offset = 0;
			ring_data->rx_curr_get_info.offset = get_info.offset;
			get_block++;
			if (get_block == ring_data->block_count)
				get_block = 0;
			ring_data->rx_curr_get_info.block_index = get_block;
			rxdp = ring_data->rx_blocks[get_block].block_virt_addr;
		}

		nic->pkts_to_process -= 1;
		if ((napi) && (!nic->pkts_to_process))
			break;
		pkt_cnt++;
		if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))
			break;
	}
	if (nic->lro) {
		/* Clear all LRO sessions before exiting */
		for (i=0; i<MAX_LRO_SESSIONS; i++) {
			struct lro *lro = &nic->lro0_n[i];
			if (lro->in_use) {
				update_L3L4_header(nic, lro);
				queue_rx_frame(lro->parent);
				clear_lro_session(lro);
			}
		}
	}

	spin_unlock(&nic->rx_lock);
}

/**
 *  tx_intr_handler - Transmit interrupt handler
 *  @nic : device private variable
 *  Description:
 *  If an interrupt was raised to indicate DMA complete of the
 *  Tx packet, this function is called. It identifies the last TxD
 *  whose buffer was freed and frees all skbs whose data have already
 *  DMA'ed into the NICs internal memory.
 *  Return Value:
 *  NONE
 */

static void tx_intr_handler(struct fifo_info *fifo_data)
{
	struct s2io_nic *nic = fifo_data->nic;
	struct net_device *dev = (struct net_device *) nic->dev;
	struct tx_curr_get_info get_info, put_info;
	struct sk_buff *skb;
	struct TxD *txdlp;

	get_info = fifo_data->tx_curr_get_info;
	memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
	txdlp = (struct TxD *) fifo_data->list_info[get_info.offset].
	    list_virt_addr;
	while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) &&
	       (get_info.offset != put_info.offset) &&
	       (txdlp->Host_Control)) {
		/* Check for TxD errors */
		if (txdlp->Control_1 & TXD_T_CODE) {
			unsigned long long err;
			err = txdlp->Control_1 & TXD_T_CODE;
			if (err & 0x1) {
				nic->mac_control.stats_info->sw_stat.
						parity_err_cnt++;
			}
			if ((err >> 48) == 0xA) {
				DBG_PRINT(TX_DBG, "TxD returned due \
						to loss of link\n");
			}
			else {
				DBG_PRINT(ERR_DBG, "***TxD error %llx\n", err);
			}
		}

		skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset);
		if (skb == NULL) {
			DBG_PRINT(ERR_DBG, "%s: Null skb ",
			__FUNCTION__);
			DBG_PRINT(ERR_DBG, "in Tx Free Intr\n");
			return;
		}

		/* Updating the statistics block */
		nic->stats.tx_bytes += skb->len;
		dev_kfree_skb_irq(skb);

		get_info.offset++;
		if (get_info.offset == get_info.fifo_len + 1)
			get_info.offset = 0;
		txdlp = (struct TxD *) fifo_data->list_info
		    [get_info.offset].list_virt_addr;
		fifo_data->tx_curr_get_info.offset =
		    get_info.offset;
	}

	spin_lock(&nic->tx_lock);
	if (netif_queue_stopped(dev))
		netif_wake_queue(dev);
	spin_unlock(&nic->tx_lock);
}

/**
 *  s2io_mdio_write - Function to write in to MDIO registers
 *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
 *  @addr     : address value
 *  @value    : data value
 *  @dev      : pointer to net_device structure
 *  Description:
 *  This function is used to write values to the MDIO registers
 *  NONE
 */
static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
{
	u64 val64 = 0x0;
	struct s2io_nic *sp = dev->priv;
	struct XENA_dev_config __iomem *bar0 = sp->bar0;

	//address transaction
	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
			| MDIO_MMD_DEV_ADDR(mmd_type)
			| MDIO_MMS_PRT_ADDR(0x0);
	writeq(val64, &bar0->mdio_control);
	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
	writeq(val64, &bar0->mdio_control);
	udelay(100);

	//Data transaction
	val64 = 0x0;
	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
			| MDIO_MMD_DEV_ADDR(mmd_type)
			| MDIO_MMS_PRT_ADDR(0x0)
			| MDIO_MDIO_DATA(value)
			| MDIO_OP(MDIO_OP_WRITE_TRANS);
	writeq(val64, &bar0->mdio_control);
	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
	writeq(val64, &bar0->mdio_control);
	udelay(100);

	val64 = 0x0;
	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
	| MDIO_MMD_DEV_ADDR(mmd_type)
	| MDIO_MMS_PRT_ADDR(0x0)
	| MDIO_OP(MDIO_OP_READ_TRANS);
	writeq(val64, &bar0->mdio_control);
	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
	writeq(val64, &bar0->mdio_control);
	udelay(100);

}

/**
 *  s2io_mdio_read - Function to write in to MDIO registers
 *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
 *  @addr     : address value
 *  @dev      : pointer to net_device structure
 *  Description:
 *  This function is used to read values to the MDIO registers
 *  NONE
 */
static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
{
	u64 val64 = 0x0;
	u64 rval64 = 0x0;
	struct s2io_nic *sp = dev->priv;
	struct XENA_dev_config __iomem *bar0 = sp->bar0;

	/* address transaction */
	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
			| MDIO_MMD_DEV_ADDR(mmd_type)
			| MDIO_MMS_PRT_ADDR(0x0);
	writeq(val64, &bar0->mdio_control);
	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
	writeq(val64, &bar0->mdio_control);
	udelay(100);

	/* Data transaction */
	val64 = 0x0;
	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
			| MDIO_MMD_DEV_ADDR(mmd_type)
			| MDIO_MMS_PRT_ADDR(0x0)
			| MDIO_OP(MDIO_OP_READ_TRANS);
	writeq(val64, &bar0->mdio_control);
	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
	writeq(val64, &bar0->mdio_control);
	udelay(100);

	/* Read the value from regs */
	rval64 = readq(&bar0->mdio_control);
	rval64 = rval64 & 0xFFFF0000;
	rval64 = rval64 >> 16;
	return rval64;
}
/**
 *  s2io_chk_xpak_counter - Function to check the status of the xpak counters
 *  @counter      : couter value to be updated
 *  @flag         : flag to indicate the status
 *  @type         : counter type
 *  Description:
 *  This function is to check the status of the xpak counters value
 *  NONE
 */

static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
{
	u64 mask = 0x3;
	u64 val64;
	int i;
	for(i = 0; i <index; i++)
		mask = mask << 0x2;

	if(flag > 0)
	{
		*counter = *counter + 1;
		val64 = *regs_stat & mask;
		val64 = val64 >> (index * 0x2);
		val64 = val64 + 1;
		if(val64 == 3)
		{
			switch(type)
			{
			case 1:
				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
					  "service. Excessive temperatures may "
					  "result in premature transceiver "
					  "failure \n");
			break;
			case 2:
				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
					  "service Excessive bias currents may "
					  "indicate imminent laser diode "
					  "failure \n");
			break;
			case 3:
				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
					  "service Excessive laser output "
					  "power may saturate far-end "
					  "receiver\n");
			break;
			default:
				DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
					  "type \n");
			}
			val64 = 0x0;
		}
		val64 = val64 << (index * 0x2);
		*regs_stat = (*regs_stat & (~mask)) | (val64);

	} else {
		*regs_stat = *regs_stat & (~mask);
	}
}

/**
 *  s2io_updt_xpak_counter - Function to update the xpak counters
 *  @dev         : pointer to net_device struct
 *  Description:
 *  This function is to upate the status of the xpak counters value
 *  NONE
 */
static void s2io_updt_xpak_counter(struct net_device *dev)
{
	u16 flag  = 0x0;
	u16 type  = 0x0;
	u16 val16 = 0x0;
	u64 val64 = 0x0;
	u64 addr  = 0x0;

	struct s2io_nic *sp = dev->priv;
	struct stat_block *stat_info = sp->mac_control.stats_info;

	/* Check the communication with the MDIO slave */
	addr = 0x0000;
	val64 = 0x0;
	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
	if((val64 == 0xFFFF) || (val64 == 0x0000))
	{
		DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
			  "Returned %llx\n", (unsigned long long)val64);
		return;
	}

	/* Check for the expecte value of 2040 at PMA address 0x0000 */
	if(val64 != 0x2040)
	{
		DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
		DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
			  (unsigned long long)val64);
		return;
	}

	/* Loading the DOM register to MDIO register */
	addr = 0xA100;
	s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);

	/* Reading the Alarm flags */
	addr = 0xA070;
	val64 = 0x0;
	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);

	flag = CHECKBIT(val64, 0x7);
	type = 1;
	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
				&stat_info->xpak_stat.xpak_regs_stat,
				0x0, flag, type);

	if(CHECKBIT(val64, 0x6))
		stat_info->xpak_stat.alarm_transceiver_temp_low++;

	flag = CHECKBIT(val64, 0x3);
	type = 2;
	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
				&stat_info->xpak_stat.xpak_regs_stat,
				0x2, flag, type);

	if(CHECKBIT(val64, 0x2))
		stat_info->xpak_stat.alarm_laser_bias_current_low++;

	flag = CHECKBIT(val64, 0x1);
	type = 3;
	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
				&stat_info->xpak_stat.xpak_regs_stat,
				0x4, flag, type);

	if(CHECKBIT(val64, 0x0))
		stat_info->xpak_stat.alarm_laser_output_power_low++;

	/* Reading the Warning flags */
	addr = 0xA074;
	val64 = 0x0;
	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);

	if(CHECKBIT(val64, 0x7))
		stat_info->xpak_stat.warn_transceiver_temp_high++;

	if(CHECKBIT(val64, 0x6))
		stat_info->xpak_stat.warn_transceiver_temp_low++;

	if(CHECKBIT(val64, 0x3))
		stat_info->xpak_stat.warn_laser_bias_current_high++;

	if(CHECKBIT(val64, 0x2))
		stat_info->xpak_stat.warn_laser_bias_current_low++;

	if(CHECKBIT(val64, 0x1))
		stat_info->xpak_stat.warn_laser_output_power_high++;

	if(CHECKBIT(val64, 0x0))
		stat_info->xpak_stat.warn_laser_output_power_low++;
}

/**
 *  alarm_intr_handler - Alarm Interrrupt handler
 *  @nic: device private variable
 *  Description: If the interrupt was neither because of Rx packet or Tx
 *  complete, this function is called. If the interrupt was to indicate
 *  a loss of link, the OSM link status handler is invoked for any other
 *  alarm interrupt the block that raised the interrupt is displayed
 *  and a H/W reset is issued.
 *  Return Value:
 *  NONE
*/

static void alarm_intr_handler(struct s2io_nic *nic)
{
	struct net_device *dev = (struct net_device *) nic->dev;
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	register u64 val64 = 0, err_reg = 0;
	u64 cnt;
	int i;
	if (atomic_read(&nic->card_state) == CARD_DOWN)
		return;
	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
	/* Handling the XPAK counters update */
	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
		/* waiting for an hour */
		nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
	} else {
		s2io_updt_xpak_counter(dev);
		/* reset the count to zero */
		nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
	}

	/* Handling link status change error Intr */
	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
		err_reg = readq(&bar0->mac_rmac_err_reg);
		writeq(err_reg, &bar0->mac_rmac_err_reg);
		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) {
			schedule_work(&nic->set_link_task);
		}
	}

	/* Handling Ecc errors */
	val64 = readq(&bar0->mc_err_reg);
	writeq(val64, &bar0->mc_err_reg);
	if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) {
		if (val64 & MC_ERR_REG_ECC_ALL_DBL) {
			nic->mac_control.stats_info->sw_stat.
				double_ecc_errs++;
			DBG_PRINT(INIT_DBG, "%s: Device indicates ",
				  dev->name);
			DBG_PRINT(INIT_DBG, "double ECC error!!\n");
			if (nic->device_type != XFRAME_II_DEVICE) {
				/* Reset XframeI only if critical error */
				if (val64 & (MC_ERR_REG_MIRI_ECC_DB_ERR_0 |
					     MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
					netif_stop_queue(dev);
					schedule_work(&nic->rst_timer_task);
					nic->mac_control.stats_info->sw_stat.
							soft_reset_cnt++;
				}
			}
		} else {
			nic->mac_control.stats_info->sw_stat.
				single_ecc_errs++;
		}
	}

	/* In case of a serious error, the device will be Reset. */
	val64 = readq(&bar0->serr_source);
	if (val64 & SERR_SOURCE_ANY) {
		nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
		DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
		DBG_PRINT(ERR_DBG, "serious error %llx!!\n",
			  (unsigned long long)val64);
		netif_stop_queue(dev);
		schedule_work(&nic->rst_timer_task);
		nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
	}

	/*
	 * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC
	 * Error occurs, the adapter will be recycled by disabling the
	 * adapter enable bit and enabling it again after the device
	 * becomes Quiescent.
	 */
	val64 = readq(&bar0->pcc_err_reg);
	writeq(val64, &bar0->pcc_err_reg);
	if (val64 & PCC_FB_ECC_DB_ERR) {
		u64 ac = readq(&bar0->adapter_control);
		ac &= ~(ADAPTER_CNTL_EN);
		writeq(ac, &bar0->adapter_control);
		ac = readq(&bar0->adapter_control);
		schedule_work(&nic->set_link_task);
	}
	/* Check for data parity error */
	val64 = readq(&bar0->pic_int_status);
	if (val64 & PIC_INT_GPIO) {
		val64 = readq(&bar0->gpio_int_reg);
		if (val64 & GPIO_INT_REG_DP_ERR_INT) {
			nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
			schedule_work(&nic->rst_timer_task);
			nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
		}
	}

	/* Check for ring full counter */
	if (nic->device_type & XFRAME_II_DEVICE) {
		val64 = readq(&bar0->ring_bump_counter1);
		for (i=0; i<4; i++) {
			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
			cnt >>= 64 - ((i+1)*16);
			nic->mac_control.stats_info->sw_stat.ring_full_cnt
				+= cnt;
		}

		val64 = readq(&bar0->ring_bump_counter2);
		for (i=0; i<4; i++) {
			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
			cnt >>= 64 - ((i+1)*16);
			nic->mac_control.stats_info->sw_stat.ring_full_cnt
				+= cnt;
		}
	}

	/* Other type of interrupts are not being handled now,  TODO */
}

/**
 *  wait_for_cmd_complete - waits for a command to complete.
 *  @sp : private member of the device structure, which is a pointer to the
 *  s2io_nic structure.
 *  Description: Function that waits for a command to Write into RMAC
 *  ADDR DATA registers to be completed and returns either success or
 *  error depending on whether the command was complete or not.
 *  Return value:
 *   SUCCESS on success and FAILURE on failure.
 */

static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
				int bit_state)
{
	int ret = FAILURE, cnt = 0, delay = 1;
	u64 val64;

	if ((bit_state != S2IO_BIT_RESET) && (bit_state != S2IO_BIT_SET))
		return FAILURE;

	do {
		val64 = readq(addr);
		if (bit_state == S2IO_BIT_RESET) {
			if (!(val64 & busy_bit)) {
				ret = SUCCESS;
				break;
			}
		} else {
			if (!(val64 & busy_bit)) {
				ret = SUCCESS;
				break;
			}
		}

		if(in_interrupt())
			mdelay(delay);
		else
			msleep(delay);

		if (++cnt >= 10)
			delay = 50;
	} while (cnt < 20);
	return ret;
}
/*
 * check_pci_device_id - Checks if the device id is supported
 * @id : device id
 * Description: Function to check if the pci device id is supported by driver.
 * Return value: Actual device id if supported else PCI_ANY_ID
 */
static u16 check_pci_device_id(u16 id)
{
	switch (id) {
	case PCI_DEVICE_ID_HERC_WIN:
	case PCI_DEVICE_ID_HERC_UNI:
		return XFRAME_II_DEVICE;
	case PCI_DEVICE_ID_S2IO_UNI:
	case PCI_DEVICE_ID_S2IO_WIN:
		return XFRAME_I_DEVICE;
	default:
		return PCI_ANY_ID;
	}
}

/**
 *  s2io_reset - Resets the card.
 *  @sp : private member of the device structure.
 *  Description: Function to Reset the card. This function then also
 *  restores the previously saved PCI configuration space registers as
 *  the card reset also resets the configuration space.
 *  Return value:
 *  void.
 */

static void s2io_reset(struct s2io_nic * sp)
{
	struct XENA_dev_config __iomem *bar0 = sp->bar0;
	u64 val64;
	u16 subid, pci_cmd;
	int i;
	u16 val16;
	DBG_PRINT(INIT_DBG,"%s - Resetting XFrame card %s\n",
			__FUNCTION__, sp->dev->name);

	/* Back up  the PCI-X CMD reg, dont want to lose MMRBC, OST settings */
	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));

	if (sp->device_type == XFRAME_II_DEVICE) {
		int ret;
		ret = pci_set_power_state(sp->pdev, 3);
		if (!ret)
			ret = pci_set_power_state(sp->pdev, 0);
		else {
			DBG_PRINT(ERR_DBG,"%s PME based SW_Reset failed!\n",
					__FUNCTION__);
			goto old_way;
		}
		msleep(20);
		goto new_way;
	}
old_way:
	val64 = SW_RESET_ALL;
	writeq(val64, &bar0->sw_reset);
new_way:
	if (strstr(sp->product_name, "CX4")) {
		msleep(750);
	}
	msleep(250);
	for (i = 0; i < S2IO_MAX_PCI_CONFIG_SPACE_REINIT; i++) {

		/* Restore the PCI state saved during initialization. */
		pci_restore_state(sp->pdev);
		pci_read_config_word(sp->pdev, 0x2, &val16);
		if (check_pci_device_id(val16) != (u16)PCI_ANY_ID)
			break;
		msleep(200);
	}

	if (check_pci_device_id(val16) == (u16)PCI_ANY_ID) {
		DBG_PRINT(ERR_DBG,"%s SW_Reset failed!\n", __FUNCTION__);
	}

	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, pci_cmd);

	s2io_init_pci(sp);

	/* Set swapper to enable I/O register access */
	s2io_set_swapper(sp);

	/* Restore the MSIX table entries from local variables */
	restore_xmsi_data(sp);

	/* Clear certain PCI/PCI-X fields after reset */
	if (sp->device_type == XFRAME_II_DEVICE) {
		/* Clear "detected parity error" bit */
		pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);

		/* Clearing PCIX Ecc status register */
		pci_write_config_dword(sp->pdev, 0x68, 0x7C);

		/* Clearing PCI_STATUS error reflected here */
		writeq(BIT(62), &bar0->txpic_int_reg);
	}

	/* Reset device statistics maintained by OS */
	memset(&sp->stats, 0, sizeof (struct net_device_stats));

	/* SXE-002: Configure link and activity LED to turn it off */
	subid = sp->pdev->subsystem_device;
	if (((subid & 0xFF) >= 0x07) &&
	    (sp->device_type == XFRAME_I_DEVICE)) {
		val64 = readq(&bar0->gpio_control);
		val64 |= 0x0000800000000000ULL;
		writeq(val64, &bar0->gpio_control);
		val64 = 0x0411040400000000ULL;
		writeq(val64, (void __iomem *)bar0 + 0x2700);
	}

	/*
	 * Clear spurious ECC interrupts that would have occured on
	 * XFRAME II cards after reset.
	 */
	if (sp->device_type == XFRAME_II_DEVICE) {
		val64 = readq(&bar0->pcc_err_reg);
		writeq(val64, &bar0->pcc_err_reg);
	}

	/* restore the previously assigned mac address */
	s2io_set_mac_addr(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);

	sp->device_enabled_once = FALSE;
}

/**
 *  s2io_set_swapper - to set the swapper controle on the card
 *  @sp : private member of the device structure,
 *  pointer to the s2io_nic structure.
 *  Description: Function to set the swapper control on the card
 *  correctly depending on the 'endianness' of the system.
 *  Return value:
 *  SUCCESS on success and FAILURE on failure.
 */

static int s2io_set_swapper(struct s2io_nic * sp)
{
	struct net_device *dev = sp->dev;
	struct XENA_dev_config __iomem *bar0 = sp->bar0;
	u64 val64, valt, valr;

	/*
	 * Set proper endian settings and verify the same by reading
	 * the PIF Feed-back register.
	 */

	val64 = readq(&bar0->pif_rd_swapper_fb);
	if (val64 != 0x0123456789ABCDEFULL) {
		int i = 0;
		u64 value[] = { 0xC30000C3C30000C3ULL,   /* FE=1, SE=1 */
				0x8100008181000081ULL,  /* FE=1, SE=0 */
				0x4200004242000042ULL,  /* FE=0, SE=1 */
				0};                     /* FE=0, SE=0 */

		while(i<4) {
			writeq(value[i], &bar0->swapper_ctrl);
			val64 = readq(&bar0->pif_rd_swapper_fb);
			if (val64 == 0x0123456789ABCDEFULL)
				break;
			i++;
		}
		if (i == 4) {
			DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
				dev->name);
			DBG_PRINT(ERR_DBG, "feedback read %llx\n",
				(unsigned long long) val64);
			return FAILURE;
		}
		valr = value[i];
	} else {
		valr = readq(&bar0->swapper_ctrl);
	}

	valt = 0x0123456789ABCDEFULL;
	writeq(valt, &bar0->xmsi_address);
	val64 = readq(&bar0->xmsi_address);

	if(val64 != valt) {
		int i = 0;
		u64 value[] = { 0x00C3C30000C3C300ULL,  /* FE=1, SE=1 */
				0x0081810000818100ULL,  /* FE=1, SE=0 */
				0x0042420000424200ULL,  /* FE=0, SE=1 */
				0};                     /* FE=0, SE=0 */

		while(i<4) {
			writeq((value[i] | valr), &bar0->swapper_ctrl);
			writeq(valt, &bar0->xmsi_address);
			val64 = readq(&bar0->xmsi_address);
			if(val64 == valt)
				break;
			i++;
		}
		if(i == 4) {
			unsigned long long x = val64;
			DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr ");
			DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);
			return FAILURE;
		}
	}
	val64 = readq(&bar0->swapper_ctrl);
	val64 &= 0xFFFF000000000000ULL;

#ifdef  __BIG_ENDIAN
	/*
	 * The device by default set to a big endian format, so a
	 * big endian driver need not set anything.
	 */
	val64 |= (SWAPPER_CTRL_TXP_FE |
		 SWAPPER_CTRL_TXP_SE |
		 SWAPPER_CTRL_TXD_R_FE |
		 SWAPPER_CTRL_TXD_W_FE |
		 SWAPPER_CTRL_TXF_R_FE |
		 SWAPPER_CTRL_RXD_R_FE |
		 SWAPPER_CTRL_RXD_W_FE |
		 SWAPPER_CTRL_RXF_W_FE |
		 SWAPPER_CTRL_XMSI_FE |
		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
	if (sp->intr_type == INTA)
		val64 |= SWAPPER_CTRL_XMSI_SE;
	writeq(val64, &bar0->swapper_ctrl);
#else
	/*
	 * Initially we enable all bits to make it accessible by the
	 * driver, then we selectively enable only those bits that
	 * we want to set.
	 */
	val64 |= (SWAPPER_CTRL_TXP_FE |
		 SWAPPER_CTRL_TXP_SE |
		 SWAPPER_CTRL_TXD_R_FE |
		 SWAPPER_CTRL_TXD_R_SE |
		 SWAPPER_CTRL_TXD_W_FE |
		 SWAPPER_CTRL_TXD_W_SE |
		 SWAPPER_CTRL_TXF_R_FE |
		 SWAPPER_CTRL_RXD_R_FE |
		 SWAPPER_CTRL_RXD_R_SE |
		 SWAPPER_CTRL_RXD_W_FE |
		 SWAPPER_CTRL_RXD_W_SE |
		 SWAPPER_CTRL_RXF_W_FE |
		 SWAPPER_CTRL_XMSI_FE |
		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
	if (sp->intr_type == INTA)
		val64 |= SWAPPER_CTRL_XMSI_SE;
	writeq(val64, &bar0->swapper_ctrl);
#endif
	val64 = readq(&bar0->swapper_ctrl);

	/*
	 * Verifying if endian settings are accurate by reading a
	 * feedback register.
	 */
	val64 = readq(&bar0->pif_rd_swapper_fb);
	if (val64 != 0x0123456789ABCDEFULL) {
		/* Endian settings are incorrect, calls for another dekko. */
		DBG_PRINT(ERR_DBG, "%s: Endian settings are wrong, ",
			  dev->name);
		DBG_PRINT(ERR_DBG, "feedback read %llx\n",
			  (unsigned long long) val64);
		return FAILURE;
	}

	return SUCCESS;
}

static int wait_for_msix_trans(struct s2io_nic *nic, int i)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	u64 val64;
	int ret = 0, cnt = 0;

	do {
		val64 = readq(&bar0->xmsi_access);
		if (!(val64 & BIT(15)))
			break;
		mdelay(1);
		cnt++;
	} while(cnt < 5);
	if (cnt == 5) {
		DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
		ret = 1;
	}

	return ret;
}

static void restore_xmsi_data(struct s2io_nic *nic)
{
	struct XENA_dev_config __iomem *bar0 = nic->bar0;
	u64 val64;
	int i;

	for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
		writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
		writeq(nic->msix_info[i].data, &bar0->xmsi_data);
		val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
		writeq(val64, &bar0->xmsi_access);