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

📄 floppy.c

📁 newos is new operation system
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.** Distributed under the terms of the NewOS License.*/#include <kernel/kernel.h>#include <boot/stage2.h>#include <kernel/debug.h>#include <kernel/heap.h>#include <kernel/sem.h>#include <kernel/smp.h>#include <kernel/int.h>#include <kernel/vm.h>#include <kernel/module.h>#include <kernel/timer.h>#include <kernel/fs/devfs.h>#include <string.h>#include <newos/errors.h>#include <kernel/bus/isa/isa.h>#define FLOPPY_TRACE 1#if FLOPPY_TRACE > 0#define TRACE(x...) dprintf("floppy: " x)#else#define TRACE(x...)#endif#define SECTORS_PER_TRACK 18#define NUM_HEADS 2#define SECTORS_PER_CYLINDER (SECTORS_PER_TRACK * NUM_HEADS)#define SECTOR_SIZE 512#define TRACK_SIZE (SECTOR_SIZE * SECTORS_PER_CYLINDER)#define NUM_TRACKS 80#define DISK_SIZE (TRACK_SIZE * NUM_TRACKS)#define MOTOR_TIMEOUT 5000000		// 10 seconds#define MOTOR_SPINUP_DELAY 500000	// 500 msecstypedef struct {	int iobase;	int drive_num;	sem_id io_completion_sem;	bool io_pending;	mutex lock;	spinlock_t spinlock;	isa_bus_manager *isa;	struct timer_event motor_timer;} floppy;typedef struct {	floppy *flp;	off_t pos;} floppy_cookie;typedef struct {	uint8 id;	uint8 drive;	uint8 cylinder;	uint8 head;	uint8 sector;	uint8 sector_size;	uint8 track_length;	uint8 gap3_length;	uint8 data_length;} floppy_command;typedef struct {	uint8 st0;	uint8 st1;	uint8 st2;	uint8 cylinder;	uint8 head;	uint8 sector;	uint8 sector_size;} floppy_result;typedef enum {	STATUS_A = 0,	STATUS_B = 1,	DIGITAL_OUT = 2,	TAPE_DRIVE = 3,	MAIN_STATUS = 4,	DATA_RATE_SELECT = 4,	DATA = 5,	DIGITAL_IN = 7,	CONFIG_CONTROL = 7} floppy_reg_selector;// function declsstatic int floppy_detect(floppy **flp, int chain, int drive);static int floppy_init(floppy *flp);static void write_reg(floppy *flp, floppy_reg_selector selector, uint8 data);static uint8 read_reg(floppy *flp, floppy_reg_selector selector);static void turn_on_motor(floppy *flp);static void turn_off_motor(floppy *flp);static void wait_for_rqm(floppy *flp);static void send_command(floppy *flp, const uint8 *data, int len);static void read_result(floppy *flp, uint8 *data, int len);static void recalibrate_drive(floppy *flp);static void config_drive(floppy *flp);static int motor_callback(void *arg);static size_t read_sectors(floppy *flp, void *buf, int lba, int num_sectors);static size_t write_sectors(floppy *flp, const void *buf, int lba, int num_sectors);static size_t read_track(floppy *flp, void *buf, int lba);static int floppy_open(dev_ident ident, dev_cookie *_cookie){	floppy *flp = (floppy *)ident;	floppy_cookie *cookie;	cookie = (floppy_cookie *)kmalloc(sizeof(floppy_cookie));	if(!cookie)		return ERR_NO_MEMORY;	cookie->flp = flp;	cookie->pos = 0;	*_cookie = cookie;	return 0;}static int floppy_freecookie(dev_cookie _cookie){	floppy_cookie *cookie = (floppy_cookie *)_cookie;	kfree(cookie);	return 0;}static int floppy_seek(dev_cookie _cookie, off_t pos, seek_type st){	floppy_cookie *cookie = (floppy_cookie *)_cookie;	int err = 0;	TRACE("seek: pos %Ld, st %d\n", pos, st);	mutex_lock(&cookie->flp->lock);	switch(st) {		case _SEEK_END:			pos += DISK_SIZE;			goto _SEEK_SET;		case _SEEK_CUR:			pos += cookie->pos;_SEEK_SET:		case _SEEK_SET:			if(pos < 0)				pos = 0;			if(pos > DISK_SIZE)				pos = DISK_SIZE;			cookie->pos = pos;			break;		default:			err = ERR_INVALID_ARGS;	}	mutex_unlock(&cookie->flp->lock);	return err;}static int floppy_close(dev_cookie _cookie){	return 0;}static ssize_t floppy_read(dev_cookie _cookie, void *_buf, off_t pos, ssize_t len){	floppy_cookie *cookie = (floppy_cookie *)_cookie;	ssize_t bytes_read = 0;	int err;	if(len <= 0)		return 0;	TRACE("read: pos %Ld, len %ld\n", pos, len);	mutex_lock(&cookie->flp->lock);	if(pos < 0)		pos = cookie->pos;	// handle partial first block	if((pos % SECTOR_SIZE) != 0) {		ssize_t toread;		char buf[SECTOR_SIZE];		err = read_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		TRACE("read: 1 pos %Ld, len %ld, bytes_read %ld\n", pos, len, bytes_read);		toread = min(len, SECTOR_SIZE);		toread = min(toread, SECTOR_SIZE - (pos % SECTOR_SIZE));		err = user_memcpy(_buf, buf + (pos % SECTOR_SIZE), toread);		if(err < 0)			goto out;		len -= toread;		bytes_read += toread;		pos += toread;	}	// read the middle blocks	while(len >= SECTOR_SIZE) {		TRACE("read: 2 pos %Ld, len %ld, bytes_read %ld\n", pos, len, bytes_read);		// try to read as many sectors as we can		err = read_sectors(cookie->flp, (char *)_buf + bytes_read, pos / SECTOR_SIZE, len / SECTOR_SIZE);		if(err <= 0)			goto out;		TRACE("write: 2 write_sectors returned %d (%d bytes)\n", err, err * SECTOR_SIZE);		len -= err * SECTOR_SIZE;		bytes_read += err * SECTOR_SIZE;		pos += err * SECTOR_SIZE;	}	// handle partial last block	if(len > 0 && (len % SECTOR_SIZE) != 0) {		char buf[SECTOR_SIZE];		err = read_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		TRACE("read: 3 pos %Ld, len %ld, bytes_read %ld\n", pos, len, bytes_read);		err = user_memcpy((char *)_buf + bytes_read, buf, len);		if(err < 0)			goto out;		bytes_read += len;		pos += len;	}	cookie->pos = pos;out:	mutex_unlock(&cookie->flp->lock);	return bytes_read;}static ssize_t floppy_write(dev_cookie _cookie, const void *_buf, off_t pos, ssize_t len){	floppy_cookie *cookie = (floppy_cookie *)_cookie;	ssize_t bytes_written = 0;	int err;	if(len <= 0)		return 0;	TRACE("write: pos %Ld, len %ld\n", pos, len);	mutex_lock(&cookie->flp->lock);	if(pos < 0)		pos = cookie->pos;	// handle partial first block	if((pos % SECTOR_SIZE) != 0) {		ssize_t towrite;		char buf[SECTOR_SIZE];		/* read in a sector */		err = read_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		/* copy the modified data over */		towrite = min(len, SECTOR_SIZE);		towrite = min(towrite, SECTOR_SIZE - (pos % SECTOR_SIZE));		err = user_memcpy(buf + (pos % SECTOR_SIZE), _buf, towrite);		if(err < 0)			goto out;		/* write this sector back out */		err = write_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		TRACE("write: 1 pos %Ld, len %ld, bytes_written %ld\n", pos, len, bytes_written);		len -= towrite;		bytes_written += towrite;		pos += towrite;	}	// write the middle blocks	while(len >= SECTOR_SIZE) {		TRACE("write: 2 pos %Ld, len %ld, bytes_written %ld\n", pos, len, bytes_written);		// try to write as many sectors as we can		err = write_sectors(cookie->flp, (char *)_buf + bytes_written, pos / SECTOR_SIZE, len / SECTOR_SIZE);		if(err <= 0)			goto out;		TRACE("write: 2 write_sectors returned %d (%d bytes)\n", err, err * SECTOR_SIZE);		len -= err * SECTOR_SIZE;		bytes_written += err * SECTOR_SIZE;		pos += err * SECTOR_SIZE;	}	// handle partial last block	if(len > 0 && (len % SECTOR_SIZE) != 0) {		char buf[SECTOR_SIZE];		/* read in a sector */		err = read_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		/* copy the modified data over */		err = user_memcpy(buf, (char *)_buf + bytes_written, len);		if(err < 0)			goto out;		/* write the sector back out */		err = write_sectors(cookie->flp, buf, pos / SECTOR_SIZE, 1);		if(err <= 0)			goto out;		TRACE("write: 3 pos %Ld, len %ld, bytes_written %ld\n", pos, len, bytes_written);		bytes_written += len;		pos += len;	}	cookie->pos = pos;out:	mutex_unlock(&cookie->flp->lock);	return bytes_written;}static int floppy_ioctl(dev_cookie _cookie, int op, void *buf, size_t len){//	floppy_cookie *cookie = (floppy_cookie *)_cookie;	int err;	dprintf("floppy_ioctl: op %d, buf %p, len %ld\n", op, buf, len);	switch(op) {		default:			err = ERR_INVALID_ARGS;	}	return err;}static struct dev_calls floppy_hooks = {	&floppy_open,	&floppy_close,	&floppy_freecookie,	&floppy_seek,	&floppy_ioctl,	&floppy_read,	&floppy_write,	/* no paging here */	NULL,	NULL,	NULL};int dev_bootstrap(void);int dev_bootstrap(void){	floppy *flp;	isa_bus_manager *isa;	if(module_get(ISA_MODULE_NAME, 0, (void **)&isa) < 0) {		dprintf("floppy_dev_init: no isa bus found..\n");		return -1;	}	dprintf("floppy_dev_init: entry\n");	// detect and setup the device	if(floppy_detect(&flp, 0, 0) < 0) {		// no floppy here		dprintf("floppy_dev_init: no device found\n");		return ERR_GENERAL;	}	flp->isa = isa;	floppy_init(flp);

⌨️ 快捷键说明

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