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

📄 mcdx.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)				> stuffp->lastsector + 1) {			xtrace(XFER,  "cut high_border\n");			stuffp->high_border = stuffp->lastsector + 1;		}		{	/* Convert the sector to be requested to MSF format */			struct cdrom_msf0 pending;			log2msf(stuffp->pending / 4, &pending);			cmd[1] = pending.minute;			cmd[2] = pending.second;			cmd[3] = pending.frame;		}		cmd[6] = (unsigned char) ((stuffp->high_border - stuffp->pending) / 4);		xtrace(XFER, "[%2d]\n", cmd[6]);		stuffp->busy = 1;		/* Now really issue the request command */		outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);    }#ifdef AK2	if ( stuffp->int_err ) {		stuffp->valid = 0;		stuffp->int_err = 0;		return -1;	}#endif /* AK2 */    stuffp->low_border = (stuffp->low_border += done) < stuffp->high_border	    ? stuffp->low_border : stuffp->high_border;    return done;}/*	Access to elements of the mcdx_drive_map members */static char* port(int *ip) { return (char*) ip[0]; }static int irq(int *ip) { return ip[1]; }/*	Misc number converters */static unsigned int bcd2uint(unsigned char c){ return (c >> 4) * 10 + (c & 0x0f); }static unsigned int uint2bcd(unsigned int ival){ return ((ival / 10) << 4) | (ival % 10); }static void log2msf(unsigned int l, struct cdrom_msf0* pmsf){    l += CD_MSF_OFFSET;    pmsf->minute = uint2bcd(l / 4500), l %= 4500;    pmsf->second = uint2bcd(l / 75);    pmsf->frame = uint2bcd(l % 75);}static unsigned int msf2log(const struct cdrom_msf0* pmsf){    return bcd2uint(pmsf->frame)    + bcd2uint(pmsf->second) * 75    + bcd2uint(pmsf->minute) * 4500    - CD_MSF_OFFSET;}int mcdx_readtoc(struct s_drive_stuff* stuffp)/*  Read the toc entries from the CD, *  Return: -1 on failure, else 0 */{	if (stuffp->toc) {		xtrace(READTOC, "ioctl() toc already read\n");		return 0;	}	xtrace(READTOC, "ioctl() readtoc for %d tracks\n",			stuffp->di.n_last - stuffp->di.n_first + 1);    if (-1 == mcdx_hold(stuffp, 1)) return -1;	xtrace(READTOC, "ioctl() tocmode\n");	if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) return -EIO;	/* all seems to be ok so far ... malloc */	{		int size;		size = sizeof(struct s_subqcode) * (stuffp->di.n_last - stuffp->di.n_first + 2);		xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);		stuffp->toc = kmalloc(size, GFP_KERNEL);		if (!stuffp->toc) {			xwarn("Cannot malloc %d bytes for toc\n", size);			mcdx_setdrivemode(stuffp, DATA, 1);			return -EIO;		}	}	/* now read actually the index */	{		int trk;		int retries;		for (trk = 0;				trk < (stuffp->di.n_last - stuffp->di.n_first + 1);				trk++)			stuffp->toc[trk].index = 0;		for (retries = 300; retries; retries--) { /* why 300? */			struct s_subqcode q;			unsigned int idx;			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {				mcdx_setdrivemode(stuffp, DATA, 1);				return -EIO;			}			idx = bcd2uint(q.index);			if ((idx > 0)					&& (idx <= stuffp->di.n_last)					&& (q.tno == 0)					&& (stuffp->toc[idx - stuffp->di.n_first].index == 0)) {				stuffp->toc[idx - stuffp->di.n_first] = q;				xtrace(READTOC, "ioctl() toc idx %d (trk %d)\n", idx, trk);				trk--;			}			if (trk == 0) break;		}		memset(&stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1],				0, sizeof(stuffp->toc[0]));		stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1].dt				= stuffp->di.msf_leadout;	}	/* unset toc mode */	xtrace(READTOC, "ioctl() undo toc mode\n");	if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))		return -EIO;#if MCDX_DEBUG && READTOC	{ int trk;	for (trk = 0;			trk < (stuffp->di.n_last - stuffp->di.n_first + 2);			trk++)		xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"				"  %02x:%02x.%02x  %02x:%02x.%02x\n",				trk + stuffp->di.n_first,				stuffp->toc[trk].control, stuffp->toc[trk].tno, stuffp->toc[trk].index,				stuffp->toc[trk].tt.minute, stuffp->toc[trk].tt.second, stuffp->toc[trk].tt.frame,				stuffp->toc[trk].dt.minute, stuffp->toc[trk].dt.second, stuffp->toc[trk].dt.frame);	}#endif	return 0;}static intmcdx_playmsf(struct s_drive_stuff* stuffp, const struct cdrom_msf* msf){    unsigned char cmd[7] = {        0, 0, 0, 0, 0, 0, 0    };	if (!stuffp->readcmd) {		xinfo("Can't play from missing disk.\n");		return -1;	}    cmd[0] = stuffp->playcmd;    cmd[1] = msf->cdmsf_min0;    cmd[2] = msf->cdmsf_sec0;    cmd[3] = msf->cdmsf_frame0;    cmd[4] = msf->cdmsf_min1;    cmd[5] = msf->cdmsf_sec1;    cmd[6] = msf->cdmsf_frame1;    xtrace(PLAYMSF, "ioctl(): play %x "            "%02x:%02x:%02x -- %02x:%02x:%02x\n",            cmd[0], cmd[1], cmd[2], cmd[3],            cmd[4], cmd[5], cmd[6]);    outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);    if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {        xwarn("playmsf() timeout\n");        return -1;    }    stuffp->audiostatus = CDROM_AUDIO_PLAY;    return 0;}static intmcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti){    struct s_subqcode* p;    struct cdrom_msf msf;    if (-1 == mcdx_readtoc(stuffp)) return -1;    if (ti) p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];    else p = &stuffp->start;    msf.cdmsf_min0 = p->dt.minute;    msf.cdmsf_sec0 = p->dt.second;    msf.cdmsf_frame0 = p->dt.frame;    if (ti) {        p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];        stuffp->stop = *p;    } else p = &stuffp->stop;    msf.cdmsf_min1 = p->dt.minute;    msf.cdmsf_sec1 = p->dt.second;    msf.cdmsf_frame1 = p->dt.frame;    return mcdx_playmsf(stuffp, &msf);}/* Drive functions ************************************************/static intmcdx_tray_move(struct cdrom_device_info * cdi, int position){    struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];    if (!stuffp->present) 		return -ENXIO;	if (!(stuffp->present & DOOR))		return -ENOSYS;  	if (position)                /* 1: eject */        	return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);	else /* 0: close */			return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);    return 1;}static intmcdx_stop(struct s_drive_stuff *stuffp, int tries){ return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); }static intmcdx_hold(struct s_drive_stuff *stuffp, int tries){ return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); }static intmcdx_requestsubqcode(struct s_drive_stuff *stuffp,        struct s_subqcode *sub,        int tries){	char buf[11];	int ans;	if (-1 == (ans = mcdx_talk(            stuffp, "\x20", 1, buf, sizeof(buf),            2 * HZ, tries)))        return -1;	sub->control = buf[1];	sub->tno = buf[2];	sub->index = buf[3];	sub->tt.minute = buf[4];	sub->tt.second = buf[5];	sub->tt.frame = buf[6];	sub->dt.minute = buf[8];	sub->dt.second = buf[9];	sub->dt.frame = buf[10];	return ans;}static intmcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, struct s_multi *multi, int tries){	char buf[5];	int ans;    if (stuffp->present & MULTI) {		ans = mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, tries);		multi->multi = buf[1];        multi->msf_last.minute = buf[2];        multi->msf_last.second = buf[3];        multi->msf_last.frame = buf[4];        return ans;    } else {        multi->multi = 0;        return 0;    }}static intmcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, int tries){	char buf[9];	int ans;	ans = mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);	if (ans == -1) {		info->n_first = 0;		info->n_last = 0;	} else {		info->n_first = bcd2uint(buf[1]);		info->n_last = bcd2uint(buf[2]);		info->msf_leadout.minute = buf[3];		info->msf_leadout.second = buf[4];		info->msf_leadout.frame = buf[5];		info->msf_first.minute = buf[6];		info->msf_first.second = buf[7];		info->msf_first.frame = buf[8];	}	return ans;}static intmcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries){	char cmd[2];	int ans;	xtrace(HW, "setdrivemode() %d\n", mode);	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))		return -1;	switch (mode) {	  case TOC: cmd[1] |= 0x04; break;	  case DATA: cmd[1] &= ~0x04; break;	  case RAW: cmd[1] |= 0x40; break;	  case COOKED: cmd[1] &= ~0x40; break;	  default: break;	}	cmd[0] = 0x50;	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);}static intmcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, int tries){	unsigned char cmd[2] = { 0xa0 };	xtrace(HW, "setdatamode() %d\n", mode);	switch (mode) {	  case MODE0: cmd[1] = 0x00; break;	  case MODE1: cmd[1] = 0x01; break;	  case MODE2: cmd[1] = 0x02; break;	  default: return -EINVAL;	}	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);}static intmcdx_config(struct s_drive_stuff *stuffp, int tries){	char cmd[4];	xtrace(HW, "config()\n");	cmd[0] = 0x90;	cmd[1] = 0x10;		/* irq enable */	cmd[2] = 0x05;		/* pre, err irq enable */	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))		return -1;	cmd[1] = 0x02;		/* dma select */	cmd[2] = 0x00;		/* no dma */	return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);}static intmcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, int tries){	char buf[3];	int ans;	if (-1 == (ans = mcdx_talk(stuffp, "\xdc",			1, buf, sizeof(buf), 2 * HZ, tries)))		return ans;	ver->code = buf[1];	ver->ver = buf[2];	return ans;}static intmcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries){	if (mode == HARD) {		outb(0, (unsigned int) stuffp->wreg_chn);		/* no dma, no irq -> hardware */		outb(0, (unsigned int) stuffp->wreg_reset);		/* hw reset */		return 0;	} else return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);}static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock){    struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];	char cmd[2] = { 0xfe };    if (!(stuffp->present & DOOR))		return -ENOSYS;    if (stuffp->present & DOOR) {        cmd[1] = lock ? 0x01 : 0x00;        return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);    } else return 0;}static intmcdx_getstatus(struct s_drive_stuff *stuffp, int tries){ return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); }static intmcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf){    unsigned long timeout = to + jiffies;    char c;    if (!buf) buf = &c;    while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {        if (time_after(jiffies, timeout)) return -1;        mcdx_delay(stuffp, delay);    }    *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff;    return 0;}static intmcdx_setattentuator(        struct s_drive_stuff* stuffp,        struct cdrom_volctrl* vol,        int tries){    char cmd[5];    cmd[0] = 0xae;    cmd[1] = vol->channel0;    cmd[2] = 0;    cmd[3] = vol->channel1;    cmd[4] = 0;    return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);}/* ex:set ts=4 sw=4 ai si: */

⌨️ 快捷键说明

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