dpt_control.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 856 行 · 第 1/2 页

C
856
字号
	return (0);}static intdpt_close(dev_t dev, int flags, int fmt, struct proc * p){	int             minor_no;	dpt_softc_t    *dpt;	minor_no = minor(dev);	dpt = dpt_minor2softc(minor_no);	if ((dpt_minor2unit(minor_no) == -1) || (dpt == NULL))		return (ENXIO);	else {		brelse(dpt_inbuf[minor_no & ~SCSI_CONTROL_MASK]);		dpt->state &= ~DPT_HA_CONTROL_ACTIVE;		return (0);	}}static intdpt_write(dev_t dev, struct uio * uio, int ioflag){	int             minor_no;	int             unit;	int             error;	minor_no = minor(dev);	if (minor_no & SCSI_CONTROL_MASK) {#ifdef DPT_DEBUG_CONTROL		printf("dpt%d:  I/O attempted to control channel (%x)\n",		       dpt_minor2unit(minor_no), minor_no);#endif		return (ENXIO);	}	unit = dpt_minor2unit(minor_no);	if (unit == -1) {		return (ENXIO);	} else if (uio->uio_resid > DPT_RW_CMD_LEN) {		return (E2BIG);	} else {		char           *cp;		int             length;		cp = dpt_inbuf[minor_no]->b_data;		length = uio->uio_resid;	/* uiomove will change it! */		if ((error = uiomove(cp, length, uio) != 0)) {#ifdef DPT_DEBUG_CONTROL			printf("dpt%d: uiomove(%x, %d, %x) failed (%d)\n",			       minor_no, cp, length, uio, error);#endif			return (error);		} else {			cp[length] = '\0';			/* A real kludge, to allow plain echo(1) to work */			if (cp[length - 1] == '\n')				cp[length - 1] = '\0';			strncpy(dpt_rw_command[unit], cp, DPT_RW_CMD_LEN);#ifdef DPT_DEBUG_CONTROL			/**			 * For lack of anything better to do;			 * For now, dump the data so we can look at it and rejoice			 */			printf("dpt%d: Command \"%s\" arrived\n",			       unit, dpt_rw_command[unit]);#endif		}	}	return (error);}static intdpt_read(dev_t dev, struct uio * uio, int ioflag){	dpt_softc_t    *dpt;	int             error;	int             minor_no;	int             ospl;	minor_no = minor(dev);	error = 0;#ifdef DPT_DEBUG_CONTROL	printf("dpt%d: read, count = %d, dev = %08x\n",	       minor_no, uio->uio_resid, dev);#endif	if (minor_no & SCSI_CONTROL_MASK) {#ifdef DPT_DEBUG_CONTROL		printf("dpt%d:  I/O attempted to control channel (%x)\n",		       dpt_minor2unit(minor_no), minor_no);#endif		return (ENXIO);	}	if (dpt_minor2unit(minor_no) == -1) {		return (ENXIO);	}	/*	 * else if ( uio->uio_resid > PAGE_SIZE ) { return(E2BIG); }	 */ 	else {		char           *work_buffer;		char           *wbp;		char           *command;		int             work_size;		int             ndx;		int             x;		if ((dpt = dpt_minor2softc(minor_no)) == NULL)			return (ENXIO);		work_buffer = (u_int8_t *) malloc(PAGE_SIZE, M_TEMP, M_WAITOK);		wbp = work_buffer;		work_size = 0;		ospl = splbio();		command = dpt_rw_command[dpt->unit];		if (strcmp(command, DPT_RW_CMD_DUMP_SOFTC) == 0) {			x = sprintf(wbp, "dpt%d:%s:%s:%s:%s:%x\n",				    dpt->unit,				    dpt->board_data.vendor,				    dpt->board_data.modelNum,				    dpt->board_data.firmware,				    dpt->board_data.protocol,				    dpt->EATA_revision);			work_size += x;			wbp += x;		} else if (strcmp(command, DPT_RW_CMD_DUMP_SYSINFO) == 0) {			x = sprintf(wbp, "dpt%d:%d:%d:%d:%d:%d:%d:%d:%d:%s:"				    "%d:%d:%d:%d:%d:%d:%d:%d\n",				    dpt->unit,				    dpt_sysinfo.drive0CMOS,				    dpt_sysinfo.drive1CMOS,				    dpt_sysinfo.numDrives,				    dpt_sysinfo.processorFamily,				    dpt_sysinfo.processorType,				    dpt_sysinfo.smartROMMajorVersion,				    dpt_sysinfo.smartROMMinorVersion,				    dpt_sysinfo.smartROMRevision,				    i2bin(dpt_sysinfo.flags,					  sizeof(dpt->queue_status) * 8),				    dpt_sysinfo.conventionalMemSize,				    dpt_sysinfo.extendedMemSize,			     dpt_sysinfo.osType, dpt_sysinfo.osMajorVersion,			 dpt_sysinfo.osMinorVersion, dpt_sysinfo.osRevision,			    dpt_sysinfo.osSubRevision, dpt_sysinfo.busType);			work_size += x;			wbp += x;			for (ndx = 0; ndx < 16; ndx++) {				if (dpt_sysinfo.drives[ndx].cylinders != 0) {					x = sprintf(wbp, "dpt%d:d%dc%dh%ds%d\n",						    dpt->unit,						    ndx,					  dpt_sysinfo.drives[ndx].cylinders,					      dpt_sysinfo.drives[ndx].heads,					   dpt_sysinfo.drives[ndx].sectors);					work_size += x;					wbp += x;				}			}		} else if (strcmp(command, DPT_RW_CMD_DUMP_METRICS) == 0) {			x = sprintf(wbp,				    "dpt%d: No metrics available.\n"				    "Run the dpt_dm command, or use the\n"			   "DPT_IOCTL_INTERNAL_METRICS ioctl system call\n",				    dpt->unit);			work_size += x;			wbp += x;		} else if (strcmp(command, DPT_RW_CMD_CLEAR_METRICS) == 0) {#ifdef DPT_MEASURE_PERFORMANCE			dpt_reset_performance(dpt);#endif				/* DPT_MEASURE_PERFORMANCE */			x = sprintf(wbp, "dpt%d: Metrics have been cleared\n",				    dpt->unit);			work_size += x;			wbp += x;		} else if (strcmp(command, DPT_RW_CMD_SHOW_LED) == 0) {			x = sprintf(wbp, "dpt%d:%s\n",				dpt->unit, i2bin(dpt_blinking_led(dpt), 8));			work_size += x;			wbp += x;		} else {#ifdef DPT_DEBUG_CONTROL			printf("dpt%d: Bad READ state (%s)\n", minor_no, command);#endif			splx(ospl);			error = EINVAL;		}		if (error == 0) {			work_buffer[work_size++] = '\0';			error = uiomove(work_buffer, work_size, uio);			uio->uio_resid = 0;#ifdef DPT_DEBUG_CONTROL			if (error) {				printf("dpt%d: READ uimove failed (%d)\n", dpt->unit, error);			}#endif		}	}	splx(ospl);	return (error);}/** * This is the control syscall interface. * It should be binary compatible with UnixWare, * if not totally syntatically so. */static intdpt_ioctl(dev_t dev, u_long cmd, caddr_t cmdarg, int flags, struct proc * p){	int             minor_no;	dpt_softc_t    *dpt;	dpt_user_softc_t udpt;	int             result;	int             ndx;	eata_pt_t      *eata_pass_thru;	minor_no = minor(dev);	result = 0;	if (!(minor_no & SCSI_CONTROL_MASK)) {#ifdef DPT_DEBUG_CONTROL		printf("dpt%d:  Control attempted to I/O channel (%x)\n",		       dpt_minor2unit(minor_no), minor_no);#endif				/* DEBUG */		return (ENXIO);	} else		minor_no &= ~SCSI_CONTROL_MASK;#ifdef DPT_DEBUG_CONTROL	printf("dpt%d: IOCTL(%x, %x, %p, %x, %p)\n",	       minor_no, dev, cmd, cmdarg, flags, p);#endif				/* DEBUG */	if ((dpt = dpt_minor2softc(minor_no)) == NULL)		return (result);	switch (cmd) {#ifdef DPT_MEASURE_PERFORMANCE	case DPT_IOCTL_INTERNAL_METRICS:	    		memcpy(cmdarg, &dpt->performance, sizeof(dpt->performance));		return (0);#endif				/* DPT_MEASURE_PERFORMANCE */	case DPT_IOCTL_SOFTC:		udpt.unit = dpt->unit;		udpt.handle_interrupts = dpt->handle_interrupts;		udpt.target_mode_enabled = dpt->target_mode_enabled;		udpt.spare = dpt->spare;		udpt.total_ccbs_count = dpt->total_ccbs_count;		udpt.free_ccbs_count = dpt->free_ccbs_count;		udpt.waiting_ccbs_count = dpt->waiting_ccbs_count;		udpt.submitted_ccbs_count = dpt->submitted_ccbs_count;		udpt.completed_ccbs_count = dpt->completed_ccbs_count;		udpt.queue_status = dpt->queue_status;		udpt.free_lock = dpt->free_lock;		udpt.waiting_lock = dpt->waiting_lock;		udpt.submitted_lock = dpt->submitted_lock;		udpt.completed_lock = dpt->completed_lock;		udpt.commands_processed = dpt->commands_processed;		udpt.lost_interrupts = dpt->lost_interrupts;		udpt.channels = dpt->channels;		udpt.max_id = dpt->max_id;		udpt.max_lun = dpt->max_lun;		udpt.io_base = dpt->io_base;		udpt.v_membase = (u_int8_t *) dpt->v_membase;		udpt.p_membase = (u_int8_t *) dpt->p_membase;		udpt.irq = dpt->irq;		udpt.dma_channel = dpt->dma_channel;		udpt.board_data = dpt->board_data;		udpt.EATA_revision = dpt->EATA_revision;		udpt.bustype = dpt->bustype;		udpt.state = dpt->state;		udpt.primary = dpt->primary;		udpt.more_support = dpt->more_support;		udpt.immediate_support = dpt->immediate_support;		udpt.broken_INQUIRY = dpt->broken_INQUIRY;		udpt.spare2 = dpt->spare2;		for (ndx = 0; ndx < MAX_CHANNELS; ndx++) {			udpt.resetlevel[ndx] = dpt->resetlevel[ndx];			udpt.hostid[ndx] = dpt->hostid[ndx];		}		udpt.last_ccb = dpt->last_ccb;		udpt.cplen = dpt->cplen;		udpt.cppadlen = dpt->cppadlen;		udpt.queuesize = dpt->queuesize;		udpt.sgsize = dpt->sgsize;		udpt.cache_type = dpt->cache_type;		udpt.cache_size = dpt->cache_size;		memcpy(cmdarg, &udpt, sizeof(dpt_user_softc_t));		return (0);	case SDI_SEND:	case DPT_IOCTL_SEND:		eata_pass_thru = (eata_pt_t *) cmdarg;		if ((eata_pass_thru->eataID[0] != 'E')		    || (eata_pass_thru->eataID[1] != 'A')		    || (eata_pass_thru->eataID[2] != 'T')		    || (eata_pass_thru->eataID[3] != 'A')) {			return (EFAULT);		}		switch (eata_pass_thru->command) {		case DPT_SIGNATURE:			return (copyout((char *) &dpt_sig,				 (caddr_t *) eata_pass_thru->command_buffer,					sizeof(dpt_sig)));		case DPT_NUMCTRLS:			return (copyout((char *) &dpt_controllers_present,				 (caddr_t *) eata_pass_thru->command_buffer,					sizeof(dpt_controllers_present)));		case DPT_CTRLINFO:			{				dpt_compat_ha_t compat_softc;				int             ndx;				compat_softc.ha_state = dpt->state;	/* Different Meaning! */				for (ndx = 0; ndx < MAX_CHANNELS; ndx++)					compat_softc.ha_id[ndx] = dpt->hostid[ndx];				compat_softc.ha_vect = dpt->irq;				compat_softc.ha_base = BaseRegister(dpt);				compat_softc.ha_max_jobs = dpt->total_ccbs_count;				compat_softc.ha_cache = dpt->cache_type;				compat_softc.ha_cachesize = dpt->cache_size;				compat_softc.ha_nbus = dpt->dma_channel + 1;				compat_softc.ha_ntargets = dpt->max_id + 1;				compat_softc.ha_nluns = dpt->max_lun + 1;				compat_softc.ha_tshift = (dpt->max_id == 7) ? 3 : 4;				compat_softc.ha_bshift = 2;				compat_softc.ha_npend = dpt->submitted_ccbs_count;				compat_softc.ha_active_jobs = dpt->waiting_ccbs_count;				strncpy(compat_softc.ha_fw_version,				    dpt->board_data.firmware,				    sizeof(compat_softc.ha_fw_version));				compat_softc.ha_ccb = NULL;				compat_softc.ha_cblist = NULL;				compat_softc.ha_dev = NULL;				compat_softc.ha_StPkt_lock = NULL;				compat_softc.ha_ccb_lock = NULL;				compat_softc.ha_LuQWaiting = NULL;				compat_softc.ha_QWait_lock = NULL;				compat_softc.ha_QWait_opri = NULL;				return (copyout((char *) &compat_softc,				 (caddr_t *) eata_pass_thru->command_buffer,						sizeof(dpt_compat_ha_t)));			}			break;		case DPT_SYSINFO:			return (copyout((char *) &dpt_sysinfo,				 (caddr_t *) eata_pass_thru->command_buffer,					sizeof(dpt_sysinfo)));		case EATAUSRCMD:			result = dpt_user_cmd(dpt, eata_pass_thru, cmdarg, minor_no);			return (result);		case DPT_BLINKLED:			result = dpt_blinking_led(dpt);			return (copyout((caddr_t) & result,				 (caddr_t *) eata_pass_thru->command_buffer,					sizeof(result)));		default:			printf("dpt%d: Invalid (%x) pass-throu command\n",			       dpt->unit, eata_pass_thru->command);			result = EINVAL;		}	default:		printf("dpt%d: Invalid (%lx) IOCTL\n", dpt->unit, cmd);		return (EINVAL);	}	return (result);}static          dpt_devsw_installed = 0;static voiddpt_drvinit(void *unused){	dev_t           dev;	if (!dpt_devsw_installed) {		if (bootverbose)			printf("DPT:  RAID Manager driver, Version %d.%d.%d\n",			       DPT_CTL_RELEASE, DPT_CTL_VERSION, DPT_CTL_PATCH);		/* Add the I/O (data) channel */		dev = makedev(CDEV_MAJOR, 0);		cdevsw_add(&dev, &dpt_cdevsw, NULL);		/* Add the Control (IOCTL) channel */		dev = makedev(CDEV_MAJOR, SCSI_CONTROL_MASK);		cdevsw_add(&dev, &dpt_cdevsw, NULL);		dpt_devsw_installed = 1;	}	dpt_get_sysinfo();}SYSINIT(dpt_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, dpt_drvinit, NULL)/* End of the dpt_control driver */

⌨️ 快捷键说明

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