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

📄 mcdx.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
					sub->cdsc_absaddr.msf.frame, sub->cdsc_reladdr.msf.minute,					sub->cdsc_reladdr.msf.second, sub->cdsc_reladdr.msf.frame);			return 0;		}		case CDROMREADTOCHDR: {			struct cdrom_tochdr *toc=(struct cdrom_tochdr *) arg;			xtrace(IOCTL, "ioctl() READTOCHDR\n");			toc->cdth_trk0 = stuffp->di.n_first;			toc->cdth_trk1 = stuffp->di.n_last;			xtrace(TOCHDR, "ioctl() track0 = %d, track1 = %d\n",					stuffp->di.n_first, stuffp->di.n_last);			return 0;		}		case CDROMPAUSE: {			xtrace(IOCTL, "ioctl() PAUSE\n");			if (stuffp->audiostatus != CDROM_AUDIO_PLAY) return -EINVAL;			if (-1 == mcdx_stop(stuffp, 1)) return -EIO;            stuffp->audiostatus = CDROM_AUDIO_PAUSED;			if (-1 == mcdx_requestsubqcode(stuffp, &stuffp->start, 1))				return -EIO;			return 0;		}		case CDROMMULTISESSION: {			struct cdrom_multisession *ms=(struct cdrom_multisession *) arg;			xtrace(IOCTL, "ioctl() MULTISESSION\n");			/* Always return stuff in LBA, and let the Uniform cdrom driver				worry about what the user actually wants */			ms->addr.lba = msf2log(&stuffp->multi.msf_last);			ms->xa_flag = !!stuffp->multi.multi;			xtrace(MS, "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",				ms->xa_flag, ms->addr.lba, stuffp->multi.msf_last.minute,                    stuffp->multi.msf_last.second,stuffp->multi.msf_last.frame); 			return 0;		}		case CDROMEJECT: {			xtrace(IOCTL, "ioctl() EJECT\n");			if (stuffp->users > 1) return -EBUSY;			return(mcdx_tray_move(cdi, 1));		}        case CDROMCLOSETRAY: {            xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");            return(mcdx_tray_move(cdi, 0));        }        case CDROMVOLCTRL: {			struct cdrom_volctrl *volctrl=(struct cdrom_volctrl *)arg;            xtrace(IOCTL, "ioctl() VOLCTRL\n");#if 0		/* not tested! */			/* adjust for the weirdness of workman (md) */			/* can't test it (hs) */			volctrl.channel2 = volctrl.channel1;			volctrl.channel1 = volctrl.channel3 = 0x00;#endif            return mcdx_setattentuator(stuffp, volctrl, 2);        }		default:			xwarn("ioctl(): unknown request 0x%04x\n", cmd);	    	return -EINVAL;	}}void do_mcdx_request(){    int dev;    struct s_drive_stuff *stuffp;  again:	if (CURRENT == NULL) {		xtrace(REQUEST, "end_request(0): CURRENT == NULL\n");		return;	}	if (CURRENT->rq_status == RQ_INACTIVE) {		xtrace(REQUEST, "end_request(0): rq_status == RQ_INACTIVE\n");		return;	}    INIT_REQUEST;    dev = MINOR(CURRENT->rq_dev);    stuffp = mcdx_stuffp[dev];	if ((dev < 0)		|| (dev >= MCDX_NDRIVES)		|| !stuffp		|| (!stuffp->present)) {		xwarn("do_request(): bad device: %s\n",				kdevname(CURRENT->rq_dev));		xtrace(REQUEST, "end_request(0): bad device\n");		end_request(0); return;    }	if (stuffp->audio) {		xwarn("do_request() attempt to read from audio cd\n");		xtrace(REQUEST, "end_request(0): read from audio\n");		end_request(0); return;	}	xtrace(REQUEST, "do_request() (%lu + %lu)\n",			CURRENT->sector, CURRENT->nr_sectors);    switch (CURRENT->cmd) {      case WRITE:	  xwarn("do_request(): attempt to write to cd!!\n");	  xtrace(REQUEST, "end_request(0): write\n");	  end_request(0); return;      case READ:	  stuffp->status = 0;	  while (CURRENT->nr_sectors) {	      int i;	      i = mcdx_transfer(stuffp,				  CURRENT->buffer,				  CURRENT->sector,				  CURRENT->nr_sectors);		  if (i == -1) {			  end_request(0);			  goto again;		  }		  CURRENT->sector += i;	 	  CURRENT->nr_sectors -= i;		  CURRENT->buffer += (i * 512);	  }	  end_request(1);	  goto again;	  xtrace(REQUEST, "end_request(1)\n");	  end_request(1);	  break;      default:	  panic(MCDX "do_request: unknown command.\n");	  break;    }    goto again;}static int mcdx_open(struct cdrom_device_info * cdi, int purpose){    struct s_drive_stuff *stuffp;	xtrace(OPENCLOSE, "open()\n");    stuffp = mcdx_stuffp[MINOR(cdi->dev)];    if (!stuffp->present) return -ENXIO;	/* Make the modules looking used ... (thanx bjorn).	 * But we shouldn't forget to decrement the module counter	 * on error return */	MOD_INC_USE_COUNT;    /* this is only done to test if the drive talks with us */    if (-1 == mcdx_getstatus(stuffp, 1)) {		MOD_DEC_USE_COUNT;		return -EIO;	}    if (stuffp->xxx) {        xtrace(OPENCLOSE, "open() media changed\n");        stuffp->audiostatus = CDROM_AUDIO_INVALID;        stuffp->readcmd = 0;        xtrace(OPENCLOSE, "open() Request multisession info\n");        if (-1 == mcdx_requestmultidiskinfo( stuffp, &stuffp->multi, 6))            	xinfo("No multidiskinfo\n");		} else {            /* multisession ? */            if (!stuffp->multi.multi)                stuffp->multi.msf_last.second = 2;            xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",                    stuffp->multi.multi,                    stuffp->multi.msf_last.minute,                    stuffp->multi.msf_last.second,                    stuffp->multi.msf_last.frame);        { ; } /* got multisession information */        /* request the disks table of contents (aka diskinfo) */        if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {            stuffp->lastsector = -1;        } else {            stuffp->lastsector = (CD_FRAMESIZE / 512)                    * msf2log(&stuffp->di.msf_leadout) - 1;            xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",                    stuffp->di.n_first,                    stuffp->di.msf_first.minute,                    stuffp->di.msf_first.second,                    stuffp->di.msf_first.frame,                    msf2log(&stuffp->di.msf_first));            xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n",                    stuffp->di.n_last,                    stuffp->di.msf_leadout.minute,                    stuffp->di.msf_leadout.second,                    stuffp->di.msf_leadout.frame,                    msf2log(&stuffp->di.msf_leadout));        }              if (stuffp->toc) {            xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);            kfree(stuffp->toc);            stuffp->toc = NULL;        }        xtrace(OPENCLOSE, "open() init irq generation\n");        if (-1 == mcdx_config(stuffp, 1)) {            MOD_DEC_USE_COUNT;            return -EIO;        }#if FALLBACK        /* Set the read speed */        xwarn("AAA %x AAA\n", stuffp->readcmd);        if (stuffp->readerrs) stuffp->readcmd = READ1X;        else stuffp->readcmd =                stuffp->present | SINGLE ? READ1X : READ2X;        xwarn("XXX %x XXX\n", stuffp->readcmd);#else        stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X;#endif        /* try to get the first sector, iff any ... */        if (stuffp->lastsector >= 0) {            char buf[512];            int ans;            int tries;            stuffp->xa = 0;            stuffp->audio = 0;            for (tries = 6; tries; tries--) {                stuffp->introk = 1;                xtrace(OPENCLOSE, "open() try as %s\n",                    stuffp->xa ? "XA" : "normal");                /* set data mode */                if (-1 == (ans = mcdx_setdatamode(stuffp,                        stuffp->xa ? MODE2 : MODE1, 1))) {                    /* MOD_DEC_USE_COUNT, return -EIO; */                    stuffp->xa = 0;                    break;                }                if ((stuffp->audio = e_audio(ans))) break;                while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))                    ;                if (ans == 1) break;                stuffp->xa = !stuffp->xa;            }        }        /* xa disks will be read in raw mode, others not */        if (-1 == mcdx_setdrivemode(stuffp,                stuffp->xa ? RAW : COOKED, 1)) {            MOD_DEC_USE_COUNT;            return -EIO;        }        if (stuffp->audio) {            xinfo("open() audio disk found\n");        } else if (stuffp->lastsector >= 0) {            xinfo("open() %s%s disk found\n",                    stuffp->xa ? "XA / " : "",                    stuffp->multi.multi ? "Multi Session" : "Single Session");        }    }	stuffp->xxx = 0;    stuffp->users++;    return 0;}static void mcdx_close(struct cdrom_device_info * cdi){    struct s_drive_stuff *stuffp;    xtrace(OPENCLOSE, "close()\n");    stuffp = mcdx_stuffp[MINOR(cdi->dev)];    --stuffp->users;    MOD_DEC_USE_COUNT;}static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr) /*	Return: 1 if media changed since last call to this function			0 otherwise */{    struct s_drive_stuff *stuffp;    xinfo("mcdx_media_changed called for device %s\n",	  kdevname(cdi->dev));	stuffp = mcdx_stuffp[MINOR(cdi->dev)];	mcdx_getstatus(stuffp, 1);	if (stuffp->yyy == 0) return 0;	stuffp->yyy = 0;	return 1;}__initfunc(void mcdx_setup(char *str, int *pi)){	if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1];	if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2];}/* DIRTY PART ******************************************************/static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)/* This routine is used for sleeping. * A jifs value <0 means NO sleeping, *              =0 means minimal sleeping (let the kernel *                 run for other processes) *              >0 means at least sleep for that amount. *	May be we could use a simple count loop w/ jumps to itself, but *	I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */{	if (jifs < 0) return;	xtrace(SLEEP, "*** delay: sleepq\n");	interruptible_sleep_on_timeout(&stuff->sleepq, jifs);	xtrace(SLEEP, "delay awoken\n");	if (signal_pending(current)) {		xtrace(SLEEP, "got signal\n");	}}static voidmcdx_intr(int irq, void *dev_id, struct pt_regs* regs){    struct s_drive_stuff *stuffp;	unsigned char b;    stuffp = mcdx_irq_map[irq];    if (stuffp == NULL ) {		xwarn("mcdx: no device for intr %d\n", irq);		return;    }#ifdef AK2	if ( !stuffp->busy && stuffp->pending )		stuffp->int_err = 1;#endif /* AK2 */	/* get the interrupt status */	b = inb((unsigned int) stuffp->rreg_status);	stuffp->introk = ~b & MCDX_RBIT_DTEN;	/* NOTE: We only should get interrupts if the data we	 * requested are ready to transfer.	 * But the drive seems to generate ``asynchronous'' interrupts	 * on several error conditions too.  (Despite the err int enable	 * setting during initialisation) */	/* if not ok, read the next byte as the drives status */	if (!stuffp->introk) {		xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);		if (~b & MCDX_RBIT_STEN) {			xinfo(  "intr() irq %d    status 0x%02x\n",					irq, inb((unsigned int) stuffp->rreg_data));		} else {			xinfo(  "intr() irq %d ambiguous hw status\n", irq);		}	} else {		xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);    }    stuffp->busy = 0;    wake_up_interruptible(&stuffp->busyq);}static intmcdx_talk (		struct s_drive_stuff *stuffp,		const unsigned char *cmd, size_t cmdlen,		void *buffer, size_t size,		unsigned int timeout, int tries)/* Send a command to the drive, wait for the result. * returns -1 on timeout, drive status otherwise * If buffer is not zero, the result (length size) is stored there. * If buffer is zero the size should be the number of bytes to read * from the drive.  These bytes are discarded. */{	int st;    char c;    int discard;	/* Somebody wants the data read? */    if ((discard = (buffer == NULL))) buffer = &c;    while (stuffp->lock) {		xtrace(SLEEP, "*** talk: lockq\n");		interruptible_sleep_on(&stuffp->lockq);		xtrace(SLEEP, "talk: awoken\n");	}    stuffp->lock = 1;	/* An operation other then reading data destroys the     * data already requested and remembered in stuffp->request, ... */    stuffp->valid = 0;#if MCDX_DEBUG & TALK	{		unsigned char i;		xtrace(TALK, "talk() %d / %d tries, res.size %d, command 0x%02x",				tries, timeout, size, (unsigned char) cmd[0]);		for (i = 1; i < cmdlen; i++) xtrace(TALK, " 0x%02x", cmd[i]);		xtrace(TALK, "\n");	}#endif    /*  give up if all tries are done (bad) or if the status     *  st != -1 (good) */	for (st = -1; st == -1 && tries; tries--) {		char *bp = (char*) buffer;		size_t sz = size;		outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen);        xtrace(TALK, "talk() command sent\n");        /* get the status byte */        if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {            xinfo("talk() %02x timed out (status), %d tr%s left\n",                    cmd[0], tries - 1, tries == 2 ? "y" : "ies");                continue;        }        st = *bp;

⌨️ 快捷键说明

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