⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdladrv.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
                        curpos = addr % winsize;  /* current window offset */                        curvec = addr - curpos;   /* current window vector */                        curlen = (len > (winsize - curpos)) ?				(winsize - curpos) : len;                        /* Relocate window and copy block of data */                        err = sdla_mapmem(hw, curvec);                        peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,				curlen);                        addr       += curlen;                        buf         = (char*)buf + curlen;                        len        -= curlen;                }                /* Restore DPM window position */                sdla_mapmem(hw, oldvec);                return err;        }}/*============================================================================ * Read data from adapter's memory to a data buffer in 4-byte chunks. * Note that we ensure that the SDLA memory address is on a 4-byte boundary * before we begin moving the data in 4-byte chunks.*/static void peek_by_4 (unsigned long src, void* buf, unsigned len){        /* byte copy data until we get to a 4-byte boundary */        while (len && (src & 0x03)) {                *(char *)buf ++ = readb(src ++);                len --;        }        /* copy data in 4-byte chunks */        while (len >= 4) {                *(unsigned long *)buf = readl(src);                buf += 4;                src += 4;                len -= 4;        }        /* byte copy any remaining data */        while (len) {                *(char *)buf ++ = readb(src ++);                len --;        }}/*============================================================================ * Write Absolute Adapter Memory. * Transfer data from data buffer to adapter's memory. * * Note: * Care should be taken when crossing dual-port memory window boundary. * This function is not atomic, so caller must disable interrupt if * interrupt routines are accessing adapter shared memory. */EXPORT_SYMBOL(sdla_poke); int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len){	if (addr + len > hw->memory)	/* verify arguments */		return -EINVAL;           if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */                poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);                return 0;	}		else {				/* copy data for the S508 adapter */    		unsigned long oldvec = hw->vector;	        unsigned winsize = hw->dpmsize;        	unsigned curpos, curlen;     /* current offset and block size */        	unsigned long curvec;        /* current DPM window vector */        	int err = 0;		while (len && !err) {                        curpos = addr % winsize;    /* current window offset */                        curvec = addr - curpos;     /* current window vector */                        curlen = (len > (winsize - curpos)) ?				(winsize - curpos) : len;                        /* Relocate window and copy block of data */                        sdla_mapmem(hw, curvec);                        poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,				curlen);	                addr       += curlen;                        buf         = (char*)buf + curlen;                        len        -= curlen;                }                /* Restore DPM window position */                sdla_mapmem(hw, oldvec);                return err;        }}/*============================================================================ * Write from a data buffer to adapter's memory in 4-byte chunks. * Note that we ensure that the SDLA memory address is on a 4-byte boundary * before we begin moving the data in 4-byte chunks.*/static void poke_by_4 (unsigned long dest, void* buf, unsigned len){        /* byte copy data until we get to a 4-byte boundary */        while (len && (dest & 0x03)) {                writeb (*(char *)buf ++, dest ++);                len --;        }        /* copy data in 4-byte chunks */        while (len >= 4) {                writel (*(unsigned long *)buf, dest);                dest += 4;                buf += 4;                len -= 4;        }        /* byte copy any remaining data */        while (len) {                writeb (*(char *)buf ++ , dest ++);                len --;        }}#ifdef	DONT_COMPIPLE_THIS#endif	/* DONT_COMPIPLE_THIS *//****** Hardware-Specific Functions *****************************************//*============================================================================ * Detect adapter type. * o if adapter type is specified then call detection routine for that adapter *   type.  Otherwise call detection routines for every adapter types until *   adapter is detected. * * Notes: * 1) Detection tests are destructive! Adapter will be left in shutdown state *    after the test. */static int sdla_detect (sdlahw_t* hw){	unsigned port = hw->port;	int err = 0;	if (!port && (hw->type != SDLA_S514))		return -EFAULT;    	switch (hw->type) {	case SDLA_S502A:		if (!detect_s502a(port)) err = -ENODEV;		break;	case SDLA_S502E:		if (!detect_s502e(port)) err = -ENODEV;		break;	case SDLA_S503:		if (!detect_s503(port)) err = -ENODEV;		break;	case SDLA_S507:		if (!detect_s507(port)) err = -ENODEV;		break;	case SDLA_S508:		if (!detect_s508(port)) err = -ENODEV;		break;	case SDLA_S514:                if (!detect_s514(hw)) err = -ENODEV;		break;	default:		if (detect_s502a(port))			hw->type = SDLA_S502A;		else if (detect_s502e(port))			hw->type = SDLA_S502E;		else if (detect_s503(port))			hw->type = SDLA_S503;		else if (detect_s507(port))			hw->type = SDLA_S507;		else if (detect_s508(port))			hw->type = SDLA_S508;		else err = -ENODEV;	}	return err;}/*============================================================================ * Autoselect memory region.  * o try all available DMP address options from the top down until success. */static int sdla_autodpm (sdlahw_t* hw){	int i, err = -EINVAL;	unsigned* opt;	switch (hw->type) {	case SDLA_S502A:		opt = s502a_dpmbase_options;		break;	case SDLA_S502E:	case SDLA_S503:	case SDLA_S508:		opt = s508_dpmbase_options;		break;	case SDLA_S507:		opt = s507_dpmbase_options;		break;	default:		return -EINVAL;	}	/* Start testing from 8th position, address         * 0xC8000 from the 508 address table.          * We don't want to test A**** addresses, since         * they are usually used for Video */	for (i = 8; i <= opt[0] && err; i++) {		hw->dpmbase = phys_to_virt(opt[i]);		err = sdla_setdpm(hw);	}	return err;}/*============================================================================ * Set up adapter dual-port memory window.  * o shut down adapter * o make sure that no physical memory exists in this region, i.e entire *   region reads 0xFF and is not writable when adapter is shut down. * o initialize adapter hardware * o make sure that region is usable with SDLA card, i.e. we can write to it *   when adapter is configured. */static int sdla_setdpm (sdlahw_t* hw){	int err;	/* Shut down card and verify memory region */	sdla_down(hw);	if (check_memregion(hw->dpmbase, hw->dpmsize))		return -EINVAL;	/* Initialize adapter and test on-board memory segment by segment.	 * If memory size appears to be less than shared memory window size,	 * assume that memory region is unusable.	 */	err = sdla_init(hw);	if (err) return err;	if (sdla_memtest(hw) < hw->dpmsize) {	/* less than window size */		sdla_down(hw);		return -EIO;	}	sdla_mapmem(hw, 0L);	/* set window vector at bottom */	return 0;}/*============================================================================ * Load adapter from the memory image of the SDLA firmware module.  * o verify firmware integrity and compatibility * o start adapter up */static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len){	int i;	/* Verify firmware signature */	if (strcmp(sfm->signature, SFM_SIGNATURE)) {		printk(KERN_INFO "%s: not SDLA firmware!\n",			modname);		return -EINVAL;	}	/* Verify firmware module format version */	if (sfm->version != SFM_VERSION) {		printk(KERN_INFO			"%s: firmware format %u rejected! Expecting %u.\n",			modname, sfm->version, SFM_VERSION);		return -EINVAL;	}	/* Verify firmware module length and checksum */	if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||		(checksum((void*)&sfm->info,		sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {		printk(KERN_INFO "%s: firmware corrupted!\n", modname);		return -EINVAL;	}	/* Announce */	printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,		(sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",		sfm->info.codeid);	if(hw->type == SDLA_S514)		printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",			modname, hw->S514_cpu_no[0]);	/* Scan through the list of compatible adapters and make sure our	 * adapter type is listed.	 */	for (i = 0;	     (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);	     ++i);		if (i == SFM_MAX_SDLA) {		printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",			modname, hw->type);		return -EINVAL;	}	/* Make sure there is enough on-board memory */	if (hw->memory < sfm->info.memsize) {		printk(KERN_INFO			"%s: firmware needs %lu bytes of on-board memory!\n",			modname, sfm->info.memsize);		return -EINVAL;	}	/* Move code onto adapter */	if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {		printk(KERN_INFO "%s: failed to load code segment!\n",			modname);		return -EIO;	}	/* Prepare boot-time configuration data and kick-off CPU */	sdla_bootcfg(hw, &sfm->info);	if (sdla_start(hw, sfm->info.startoffs)) {		printk(KERN_INFO "%s: Damn... Adapter won't start!\n",			modname);		return -EIO;	}	/* position DPM window over the mailbox and enable interrupts */        if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {		printk(KERN_INFO "%s: adapter hardware failure!\n",			modname);		return -EIO;	}	hw->fwid = sfm->info.codeid;		/* set firmware ID */	return 0;}/*============================================================================ * Initialize SDLA hardware: setup memory window, IRQ, etc. */static int sdla_init (sdlahw_t* hw){	int i;	for (i = 0; i < SDLA_MAXIORANGE; ++i)		hw->regs[i] = 0;	switch (hw->type) {	case SDLA_S502A: return init_s502a(hw);	case SDLA_S502E: return init_s502e(hw);	case SDLA_S503:  return init_s503(hw);	case SDLA_S507:  return init_s507(hw);	case SDLA_S508:  return init_s508(hw);	}	return -EINVAL;}/*============================================================================ * Test adapter on-board memory. * o slide DPM window from the bottom up and test adapter memory segment by *   segment. * Return adapter memory size. */static unsigned long sdla_memtest (sdlahw_t* hw){	unsigned long memsize;	unsigned winsize;	for (memsize = 0, winsize = hw->dpmsize;	     !sdla_mapmem(hw, memsize) &&		(test_memregion(hw->dpmbase, winsize) == winsize)	     ;	     memsize += winsize)	;	hw->memory = memsize;	return memsize;}/*============================================================================ * Prepare boot-time firmware configuration data. * o position DPM window * o initialize configuration data area */static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo){	unsigned char* data;	if (!sfminfo->datasize) return 0;	/* nothing to do */	if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)		return -EIO;	if(hw->type == SDLA_S514)                data = (void*)(hw->dpmbase + sfminfo->dataoffs);        else                data = (void*)((u8 *)hw->dpmbase +                        (sfminfo->dataoffs - hw->vector));	memset_io (data, 0, sfminfo->datasize);	writeb (make_config_byte(hw), &data[0x00]);	switch (sfminfo->codeid) {	case SFID_X25_502:	case SFID_X25_508:                writeb (3, &data[0x01]);        /* T1 timer */                writeb (10, &data[0x03]);       /* N2 */                writeb (7, &data[0x06]);        /* HDLC window size */                writeb (1, &data[0x0B]);        /* DTE */                writeb (2, &data[0x0C]);        /* X.25 packet window size */                writew (128, &data[0x0D]);	/* default X.25 data size */                writew (128, &data[0x0F]);	/* maximum X.25 data size */		break;	}	return 0;}/*============================================================================ * Prepare configuration byte identifying adapter type and CPU clock rate. */static unsigned char make_config_byte (sdlahw_t* hw){	unsigned char byte = 0;	switch (hw->pclk) {		case 5000:  byte = 0x01; break;		case 7200:  byte = 0x02; break;		case 8000:  byte = 0x03; break;		case 10000: byte = 0x04; break;		case 16000: byte = 0x05; break;	}	switch (hw->type) {		case SDLA_S502E: byte |= 0x80; break;		case SDLA_S503:  byte |= 0x40; break;	}	return byte;}/*============================================================================ * Start adapter's CPU. * o calculate a pointer to adapter's cold boot entry point

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -