cregit-Linux how code gets into the kernel

Release 4.11 drivers/block/paride/ppc6lnx.c

/*
        ppc6lnx.c (c) 2001 Micro Solutions Inc.
                Released under the terms of the GNU General Public license

        ppc6lnx.c  is a par of the protocol driver for the Micro Solutions
                "BACKPACK" parallel port IDE adapter
                (Works on Series 6 drives)

*/

//***************************************************************************

// PPC 6 Code in C sanitized for LINUX
// Original x86 ASM by Ron, Converted to C by Clive

//***************************************************************************



#define port_stb					1

#define port_afd					2

#define cmd_stb						port_afd

#define port_init					4

#define data_stb					port_init

#define port_sel					8

#define port_int					16

#define port_dir					0x20


#define ECR_EPP	0x80

#define ECR_BI	0x20

//***************************************************************************

//  60772 Commands


#define ACCESS_REG				0x00

#define ACCESS_PORT				0x40


#define ACCESS_READ				0x00

#define ACCESS_WRITE			0x20

//  60772 Command Prefix


#define CMD_PREFIX_SET		0xe0		
// Special command that modifies the next command's operation

#define CMD_PREFIX_RESET	0xc0		
// Resets current cmd modifier reg bits
 
#define PREFIX_IO16			0x01		
// perform 16-bit wide I/O
 
#define PREFIX_FASTWR		0x04		
// enable PPC mode fast-write
 
#define PREFIX_BLK				0x08		
// enable block transfer mode

// 60772 Registers


#define REG_STATUS				0x00		
// status register
 
#define STATUS_IRQA			0x01		
// Peripheral IRQA line
 
#define STATUS_EEPROM_DO	0x40		
// Serial EEPROM data bit

#define REG_VERSION				0x01		
// PPC version register (read)

#define REG_HWCFG					0x02		
// Hardware Config register

#define REG_RAMSIZE				0x03		
// Size of RAM Buffer
 
#define RAMSIZE_128K			0x02

#define REG_EEPROM				0x06		
// EEPROM control register
 
#define EEPROM_SK				0x01		
// eeprom SK bit
 
#define EEPROM_DI				0x02		
// eeprom DI bit
 
#define EEPROM_CS				0x04		
// eeprom CS bit
 
#define EEPROM_EN				0x08		
// eeprom output enable

#define REG_BLKSIZE				0x08		
// Block transfer len (24 bit)

//***************************************************************************


typedef struct ppc_storage {
	
u16	lpt_addr;				// LPT base address
	
u8	ppc_id;
	
u8	mode;						// operating mode
					// 0 = PPC Uni SW
					// 1 = PPC Uni FW
					// 2 = PPC Bi SW
					// 3 = PPC Bi FW
					// 4 = EPP Byte
					// 5 = EPP Word
					// 6 = EPP Dword
	
u8	ppc_flags;
	
u8	org_data;				// original LPT data port contents
	
u8	org_ctrl;				// original LPT control port contents
	
u8	cur_ctrl;				// current control port contents
} 
Interface;

//***************************************************************************

// ppc_flags


#define fifo_wait					0x10

//***************************************************************************

// DONT CHANGE THESE LEST YOU BREAK EVERYTHING - BIT FIELD DEPENDENCIES


#define PPCMODE_UNI_SW		0

#define PPCMODE_UNI_FW		1

#define PPCMODE_BI_SW			2

#define PPCMODE_BI_FW			3

#define PPCMODE_EPP_BYTE	4

#define PPCMODE_EPP_WORD	5

#define PPCMODE_EPP_DWORD	6

//***************************************************************************

static int ppc6_select(Interface *ppc);
static void ppc6_deselect(Interface *ppc);
static void ppc6_send_cmd(Interface *ppc, u8 cmd);
static void ppc6_wr_data_byte(Interface *ppc, u8 data);
static u8 ppc6_rd_data_byte(Interface *ppc);
static u8 ppc6_rd_port(Interface *ppc, u8 port);
static void ppc6_wr_port(Interface *ppc, u8 port, u8 data);
static void ppc6_rd_data_blk(Interface *ppc, u8 *data, long count);
static void ppc6_wait_for_fifo(Interface *ppc);
static void ppc6_wr_data_blk(Interface *ppc, u8 *data, long count);
static void ppc6_rd_port16_blk(Interface *ppc, u8 port, u8 *data, long length);
static void ppc6_wr_port16_blk(Interface *ppc, u8 port, u8 *data, long length);
static void ppc6_wr_extout(Interface *ppc, u8 regdata);
static int ppc6_open(Interface *ppc);
static void ppc6_close(Interface *ppc);

//***************************************************************************


static int ppc6_select(Interface *ppc) { u8 i, j, k; i = inb(ppc->lpt_addr + 1); if (i & 1) outb(i, ppc->lpt_addr + 1); ppc->org_data = inb(ppc->lpt_addr); ppc->org_ctrl = inb(ppc->lpt_addr + 2) & 0x5F; // readback ctrl ppc->cur_ctrl = ppc->org_ctrl; ppc->cur_ctrl |= port_sel; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); if (ppc->org_data == 'b') outb('x', ppc->lpt_addr); outb('b', ppc->lpt_addr); outb('p', ppc->lpt_addr); outb(ppc->ppc_id, ppc->lpt_addr); outb(~ppc->ppc_id,ppc->lpt_addr); ppc->cur_ctrl &= ~port_sel; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); ppc->cur_ctrl = (ppc->cur_ctrl & port_int) | port_init; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); i = ppc->mode & 0x0C; if (i == 0) i = (ppc->mode & 2) | 1; outb(i, ppc->lpt_addr); ppc->cur_ctrl |= port_sel; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); // DELAY ppc->cur_ctrl |= port_afd; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); j = ((i & 0x08) << 4) | ((i & 0x07) << 3); k = inb(ppc->lpt_addr + 1) & 0xB8; if (j == k) { ppc->cur_ctrl &= ~port_afd; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); k = (inb(ppc->lpt_addr + 1) & 0xB8) ^ 0xB8; if (j == k) { if (i & 4) // EPP ppc->cur_ctrl &= ~(port_sel | port_init); else // PPC/ECP ppc->cur_ctrl &= ~port_sel; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); return(1); } } outb(ppc->org_ctrl, ppc->lpt_addr + 2); outb(ppc->org_data, ppc->lpt_addr); return(0); // FAIL }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds44099.77%150.00%
Al Viro10.23%150.00%
Total441100.00%2100.00%

//***************************************************************************
static void ppc6_deselect(Interface *ppc) { if (ppc->mode & 4) // EPP ppc->cur_ctrl |= port_init; else // PPC/ECP ppc->cur_ctrl |= port_sel; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); outb(ppc->org_data, ppc->lpt_addr); outb((ppc->org_ctrl | port_sel), ppc->lpt_addr + 2); outb(ppc->org_ctrl, ppc->lpt_addr + 2); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds8698.85%150.00%
Al Viro11.15%150.00%
Total87100.00%2100.00%

//***************************************************************************
static void ppc6_send_cmd(Interface *ppc, u8 cmd) { switch(ppc->mode) { case PPCMODE_UNI_SW : case PPCMODE_UNI_FW : case PPCMODE_BI_SW : case PPCMODE_BI_FW : { outb(cmd, ppc->lpt_addr); ppc->cur_ctrl ^= cmd_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_BYTE : case PPCMODE_EPP_WORD : case PPCMODE_EPP_DWORD : { outb(cmd, ppc->lpt_addr + 3); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds8698.85%150.00%
Al Viro11.15%150.00%
Total87100.00%2100.00%

//***************************************************************************
static void ppc6_wr_data_byte(Interface *ppc, u8 data) { switch(ppc->mode) { case PPCMODE_UNI_SW : case PPCMODE_UNI_FW : case PPCMODE_BI_SW : case PPCMODE_BI_FW : { outb(data, ppc->lpt_addr); ppc->cur_ctrl ^= data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_BYTE : case PPCMODE_EPP_WORD : case PPCMODE_EPP_DWORD : { outb(data, ppc->lpt_addr + 4); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds8698.85%150.00%
Al Viro11.15%150.00%
Total87100.00%2100.00%

//***************************************************************************
static u8 ppc6_rd_data_byte(Interface *ppc) { u8 data = 0; switch(ppc->mode) { case PPCMODE_UNI_SW : case PPCMODE_UNI_FW : { ppc->cur_ctrl = (ppc->cur_ctrl & ~port_stb) ^ data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); // DELAY data = inb(ppc->lpt_addr + 1); data = ((data & 0x80) >> 1) | ((data & 0x38) >> 3); ppc->cur_ctrl |= port_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); // DELAY data |= inb(ppc->lpt_addr + 1) & 0xB8; break; } case PPCMODE_BI_SW : case PPCMODE_BI_FW : { ppc->cur_ctrl |= port_dir; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); ppc->cur_ctrl = (ppc->cur_ctrl | port_stb) ^ data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); data = inb(ppc->lpt_addr); ppc->cur_ctrl &= ~port_stb; outb(ppc->cur_ctrl,ppc->lpt_addr + 2); ppc->cur_ctrl &= ~port_dir; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_BYTE : case PPCMODE_EPP_WORD : case PPCMODE_EPP_DWORD : { outb((ppc->cur_ctrl | port_dir),ppc->lpt_addr + 2); data = inb(ppc->lpt_addr + 4); outb(ppc->cur_ctrl,ppc->lpt_addr + 2); break; } } return(data); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds28899.65%266.67%
Al Viro10.35%133.33%
Total289100.00%3100.00%

//***************************************************************************
static u8 ppc6_rd_port(Interface *ppc, u8 port) { ppc6_send_cmd(ppc,(u8)(port | ACCESS_PORT | ACCESS_READ)); return(ppc6_rd_data_byte(ppc)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3697.30%150.00%
Al Viro12.70%150.00%
Total37100.00%2100.00%

//***************************************************************************
static void ppc6_wr_port(Interface *ppc, u8 port, u8 data) { ppc6_send_cmd(ppc,(u8)(port | ACCESS_PORT | ACCESS_WRITE)); ppc6_wr_data_byte(ppc, data); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3897.44%150.00%
Al Viro12.56%150.00%
Total39100.00%2100.00%

//***************************************************************************
static void ppc6_rd_data_blk(Interface *ppc, u8 *data, long count) { switch(ppc->mode) { case PPCMODE_UNI_SW : case PPCMODE_UNI_FW : { while(count) { u8 d; ppc->cur_ctrl = (ppc->cur_ctrl & ~port_stb) ^ data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); // DELAY d = inb(ppc->lpt_addr + 1); d = ((d & 0x80) >> 1) | ((d & 0x38) >> 3); ppc->cur_ctrl |= port_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); // DELAY d |= inb(ppc->lpt_addr + 1) & 0xB8; *data++ = d; count--; } break; } case PPCMODE_BI_SW : case PPCMODE_BI_FW : { ppc->cur_ctrl |= port_dir; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); ppc->cur_ctrl |= port_stb; while(count) { ppc->cur_ctrl ^= data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); *data++ = inb(ppc->lpt_addr); count--; } ppc->cur_ctrl &= ~port_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); ppc->cur_ctrl &= ~port_dir; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_BYTE : { outb((ppc->cur_ctrl | port_dir), ppc->lpt_addr + 2); // DELAY while(count) { *data++ = inb(ppc->lpt_addr + 4); count--; } outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_WORD : { outb((ppc->cur_ctrl | port_dir), ppc->lpt_addr + 2); // DELAY while(count > 1) { *((u16 *)data) = inw(ppc->lpt_addr + 4); data += 2; count -= 2; } while(count) { *data++ = inb(ppc->lpt_addr + 4); count--; } outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } case PPCMODE_EPP_DWORD : { outb((ppc->cur_ctrl | port_dir),ppc->lpt_addr + 2); // DELAY while(count > 3) { *((u32 *)data) = inl(ppc->lpt_addr + 4); data += 4; count -= 4; } while(count) { *data++ = inb(ppc->lpt_addr + 4); count--; } outb(ppc->cur_ctrl, ppc->lpt_addr + 2); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds50499.80%266.67%
Al Viro10.20%133.33%
Total505100.00%3100.00%

//***************************************************************************
static void ppc6_wait_for_fifo(Interface *ppc) { int i; if (ppc->ppc_flags & fifo_wait) { for(i=0; i<20; i++) inb(ppc->lpt_addr + 1); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4497.78%150.00%
Al Viro12.22%150.00%
Total45100.00%2100.00%

//***************************************************************************
static void ppc6_wr_data_blk(Interface *ppc, u8 *data, long count) { switch(ppc->mode) { case PPCMODE_UNI_SW : case PPCMODE_BI_SW : { while(count--) { outb(*data++, ppc->lpt_addr); ppc->cur_ctrl ^= data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); } break; } case PPCMODE_UNI_FW : case PPCMODE_BI_FW : { u8 this, last; ppc6_send_cmd(ppc,(CMD_PREFIX_SET | PREFIX_FASTWR)); ppc->cur_ctrl |= port_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); last = *data; outb(last, ppc->lpt_addr); while(count) { this = *data++; count--; if (this == last) { ppc->cur_ctrl ^= data_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); } else { outb(this, ppc->lpt_addr); last = this; } } ppc->cur_ctrl &= ~port_stb; outb(ppc->cur_ctrl, ppc->lpt_addr + 2); ppc6_send_cmd(ppc,(CMD_PREFIX_RESET | PREFIX_FASTWR)); break; } case PPCMODE_EPP_BYTE : { while(count) { outb(*data++,ppc->lpt_addr + 4); count--; } ppc6_wait_for_fifo(ppc); break; } case PPCMODE_EPP_WORD : { while(count > 1) { outw(*((u16 *)data),ppc->lpt_addr + 4); data += 2; count -= 2; } while(count) { outb(*data++,ppc->lpt_addr + 4); count--; } ppc6_wait_for_fifo(ppc); break; } case PPCMODE_EPP_DWORD : { while(count > 3) { outl(*((u32 *)data),ppc->lpt_addr + 4); data += 4; count -= 4; } while(count) { outb(*data++,ppc->lpt_addr + 4); count--; } ppc6_wait_for_fifo(ppc); break; } } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds38499.74%150.00%
Al Viro10.26%150.00%
Total385100.00%2100.00%

//***************************************************************************
static void ppc6_rd_port16_blk(Interface *ppc, u8 port, u8 *data, long length) { length = length << 1; ppc6_send_cmd(ppc, (REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE)); ppc6_wr_data_byte(ppc,(u8)length); ppc6_wr_data_byte(ppc,(u8)(length >> 8)); ppc6_wr_data_byte(ppc,0); ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK)); ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_READ)); ppc6_rd_data_blk(ppc, data, length); ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds12099.17%150.00%
Al Viro10.83%150.00%
Total121100.00%2100.00%

//***************************************************************************
static void ppc6_wr_port16_blk(Interface *ppc, u8 port, u8 *data, long length) { length = length << 1; ppc6_send_cmd(ppc, (REG_BLKSIZE | ACCESS_REG | ACCESS_WRITE)); ppc6_wr_data_byte(ppc,(u8)length); ppc6_wr_data_byte(ppc,(u8)(length >> 8)); ppc6_wr_data_byte(ppc,0); ppc6_send_cmd(ppc, (CMD_PREFIX_SET | PREFIX_IO16 | PREFIX_BLK)); ppc6_send_cmd(ppc, (u8)(port | ACCESS_PORT | ACCESS_WRITE)); ppc6_wr_data_blk(ppc, data, length); ppc6_send_cmd(ppc, (CMD_PREFIX_RESET | PREFIX_IO16 | PREFIX_BLK)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds12099.17%266.67%
Al Viro10.83%133.33%
Total121100.00%3100.00%

//***************************************************************************
static void ppc6_wr_extout(Interface *ppc, u8 regdata) { ppc6_send_cmd(ppc,(REG_VERSION | ACCESS_REG | ACCESS_WRITE)); ppc6_wr_data_byte(ppc, (u8)((regdata & 0x03) << 6)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4397.73%150.00%
Al Viro12.27%150.00%
Total44100.00%2100.00%

//***************************************************************************
static int ppc6_open(Interface *ppc) { int ret; ret = ppc6_select(ppc); if (ret == 0) return(ret); ppc->ppc_flags &= ~fifo_wait; ppc6_send_cmd(ppc, (ACCESS_REG | ACCESS_WRITE | REG_RAMSIZE)); ppc6_wr_data_byte(ppc, RAMSIZE_128K); ppc6_send_cmd(ppc, (ACCESS_REG | ACCESS_READ | REG_VERSION)); if ((ppc6_rd_data_byte(ppc) & 0x3F) == 0x0C) ppc->ppc_flags |= fifo_wait; return(ret); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds9498.95%150.00%
Al Viro11.05%150.00%
Total95100.00%2100.00%

//***************************************************************************
static void ppc6_close(Interface *ppc) { ppc6_deselect(ppc); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1493.33%150.00%
Al Viro16.67%150.00%
Total15100.00%2100.00%

//***************************************************************************

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds280298.91%266.67%
Al Viro311.09%133.33%
Total2833100.00%3100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.