S: 23743 Groemitz
S: Germany
-N: Paul Russell
-E: Paul.Russell@rustcorp.com.au
+N: Paul `Rusty' Russell
+E: rusty@linuxcare.com
W: http://www.rustcorp.com
D: Ruggedly handsome.
-D: Developed Generic IP Firewalling Chains with Michael Neuling.
+D: netfilter, ipchains with Michael Neuling.
+S: 301/222 City Walk
+S: Canberra ACT 2601
+S: Australia
N: Thomas Sailer
E: sailer@ife.ee.ethz.ch
DRIVERS += drivers/char/drm/drm.o
endif
-ifdef CONFIG_AGP
+ifeq ($(CONFIG_AGP),y)
DRIVERS += drivers/char/agp/agp.o
endif
endif
ifdef CONFIG_VT
-DRIVERS := $(DRIVERS) drivers/video/video.a
+DRIVERS := $(DRIVERS) drivers/video/video.o
endif
ifeq ($(CONFIG_PARIDE),y)
# CONFIG_CODA_FS is not set
CONFIG_NFS_FS=y
CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
# CONFIG_SMB_FS is not set
*c = boot_cpu_data;
c->pte_quick = 0;
c->pmd_quick = 0;
- c->pgd_quick = 0;
c->pgtable_cache_sz = 0;
identify_cpu(c);
/*
int freed = 0;
if(pgtable_cache_size > high) {
do {
- if(pgd_quicklist)
- mmlist_modify_lock(), \
- free_pgd_slow(get_pgd_fast()), \
- mmlist_modify_unlock(), \
+ if(pgd_quicklist) {
+ mmlist_modify_lock();
+ free_pgd_slow(get_pgd_fast());
+ mmlist_modify_unlock();
freed++;
+ }
if(pmd_quicklist)
free_pmd_slow(get_pmd_fast()), freed++;
if(pte_quicklist)
static
-void cdrom_analyze_sense_data (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf,
+void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
struct packet_command *failed_command)
{
if (reqbuf->sense_key == NOT_READY ||
* In the case of NOT_READY, if SKSV is set the drive can
* give us nice ETA readings.
*/
- if (reqbuf->sense_key == NOT_READY &&
- (reqbuf->sense_key_specific[0] & 0x80)) {
- int progress = (reqbuf->sense_key_specific[1] << 8 |
- reqbuf->sense_key_specific[2]) * 100;
+ if (reqbuf->sense_key == NOT_READY && (reqbuf->sks[0] & 0x80)) {
+ int progress = (reqbuf->sks[1] << 8 | reqbuf->sks[2]) * 100;
printk(" Command is %02d%% complete\n", progress / 0xffff);
}
if (reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->sense_key_specific[0] & 0x80) != 0) {
+ (reqbuf->sks[0] & 0x80) != 0) {
printk (" Error in %s byte %d",
- (reqbuf->sense_key_specific[0] & 0x40) != 0
- ? "command packet"
- : "command data",
- (reqbuf->sense_key_specific[1] << 8) +
- reqbuf->sense_key_specific[2]);
-
- if ((reqbuf->sense_key_specific[0] & 0x40) != 0) {
- printk (" bit %d",
- reqbuf->sense_key_specific[0] & 0x07);
- }
+ (reqbuf->sks[0] & 0x40) != 0 ?
+ "command packet" : "command data",
+ (reqbuf->sks[1] << 8) + reqbuf->sks[2]);
+
+ if ((reqbuf->sks[0] & 0x40) != 0)
+ printk (" bit %d", reqbuf->sks[0] & 0x07);
printk ("\n");
}
static void cdrom_queue_request_sense (ide_drive_t *drive,
struct semaphore *sem,
- struct atapi_request_sense *reqbuf,
struct packet_command *failed_command)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq;
struct packet_command *pc;
- int len;
-
- /* If the request didn't explicitly specify where
- to put the sense data, use the statically allocated structure. */
- if (reqbuf == NULL)
- reqbuf = &info->sense_data;
/* Make up a new request to retrieve sense information. */
-
pc = &info->request_sense_pc;
- memset (pc, 0, sizeof (*pc));
-
- /* The request_sense structure has an odd number of (16-bit) words,
- which won't work well with 32-bit transfers. However, we don't care
- about the last two bytes, so just truncate the structure down
- to an even length. */
- len = sizeof (*reqbuf) / 4;
- len *= 4;
+ memset(pc, 0, sizeof (*pc));
pc->c[0] = GPCMD_REQUEST_SENSE;
- pc->c[4] = (unsigned char) len;
- pc->buffer = (char *)reqbuf;
- pc->buflen = len;
- pc->sense_data = (struct atapi_request_sense *)failed_command;
- /* stuff the sense request in front of our current request */
+ /* just get the first 18 bytes of the sense info, there might not
+ * be more available */
+ pc->c[4] = pc->buflen = 18;
+ pc->buffer = (char *)&info->sense_data;
+ pc->sense_data = (struct request_sense *)failed_command;
+ /* stuff the sense request in front of our current request */
rq = &info->request_sense_request;
ide_init_drive_cmd (rq);
rq->cmd = REQUEST_SENSE_COMMAND;
struct packet_command *pc = (struct packet_command *)
rq->buffer;
cdrom_analyze_sense_data (drive,
- (struct atapi_request_sense *) (pc->buffer - pc->c[4]),
+ (struct request_sense *) (pc->buffer - pc->c[4]),
(struct packet_command *) pc->sense_data);
}
if (rq->cmd == READ && !rq->current_nr_sectors)
cdrom_end_request (1, drive);
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense (drive, sem,
- pc->sense_data, pc);
+ cdrom_queue_request_sense(drive, sem, pc);
} else {
/* Handle errors from READ requests. */
/* If we got a CHECK_CONDITION status,
queue a request sense command. */
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense (drive,
- NULL, NULL, NULL);
+ cdrom_queue_request_sense(drive, NULL, NULL);
}
}
*/
/* Forward declarations. */
-static int
-cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- struct atapi_request_sense *reqbuf);
+static int cdrom_lockdoor(ide_drive_t *drive, int lockflag);
/* Interrupt routine for packet command completion. */
static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
int ireason, len, stat, thislen;
struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
+ struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
+ pc->sense_data = &info->sense_data;
+
/* Check for errors. */
if (cdrom_decode_status (&startstop, drive, 0, &stat))
return startstop;
}
static
-int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
+int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
{
- struct atapi_request_sense my_reqbuf;
int retries = 10;
struct request req;
- /* If our caller has not provided a place to stick any sense data,
- use our own area. */
- if (pc->sense_data == NULL)
- pc->sense_data = &my_reqbuf;
- pc->sense_data->sense_key = 0;
-
/* Start of retry loop. */
do {
ide_init_drive_cmd (&req);
/* The request failed. Retry if it was due to a unit
attention status
(usually means media was changed). */
- struct atapi_request_sense *reqbuf = pc->sense_data;
+ struct request_sense *reqbuf = pc->sense_data;
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change (drive);
} while (pc->stat != 0 && retries >= 0);
/* Return an error if the command failed. */
- if (pc->stat != 0)
+ if (pc->stat)
return -EIO;
- else {
- /* The command succeeded. If it was anything other than
- a request sense, eject, or door lock command,
- and we think that the door is presently unlocked, lock it
- again. (The door was probably unlocked via an explicit
- CDROMEJECT ioctl.) */
- if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
- (pc->c[0] != GPCMD_TEST_UNIT_READY &&
- pc->c[0] != GPCMD_REQUEST_SENSE &&
- pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != GPCMD_START_STOP_UNIT &&
- pc->c[0] != GPCMD_MODE_SENSE_10 &&
- pc->c[0] != GPCMD_MODE_SELECT_10)) {
- (void) cdrom_lockdoor (drive, 1, NULL);
- }
- return 0;
+
+ /* The command succeeded. If it was anything other than
+ a request sense, eject, or door lock command,
+ and we think that the door is presently unlocked, lock it
+ again. (The door was probably unlocked via an explicit
+ CDROMEJECT ioctl.) */
+ if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
+ (pc->c[0] != GPCMD_TEST_UNIT_READY &&
+ pc->c[0] != GPCMD_REQUEST_SENSE &&
+ pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
+ pc->c[0] != GPCMD_START_STOP_UNIT &&
+ pc->c[0] != GPCMD_MODE_SENSE_10 &&
+ pc->c[0] != GPCMD_MODE_SELECT_10)) {
+ (void) cdrom_lockdoor (drive, 1);
}
+ return 0;
}
/****************************************************************************
* Ioctl handling.
*
* Routines which queue packet commands take as a final argument a pointer
- * to an atapi_request_sense struct. If execution of the command results
+ * to a request_sense struct. If execution of the command results
* in an error with a CHECK CONDITION status, this structure will be filled
* with the results of the subsequent request sense command. The pointer
* can also be NULL, in which case no sense information is returned.
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
-
-static int
-cdrom_check_status (ide_drive_t *drive,
- struct atapi_request_sense *reqbuf)
+static int cdrom_check_status (ide_drive_t *drive)
{
struct packet_command pc;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
- memset (&pc, 0, sizeof (pc));
+ memset(&pc, 0, sizeof(pc));
- pc.sense_data = reqbuf;
pc.c[0] = GPCMD_TEST_UNIT_READY;
#if ! STANDARD_ATAPI
pc.c[7] = cdi->sanyo_slot % 3;
#endif /* not STANDARD_ATAPI */
- return cdrom_queue_packet_command (drive, &pc);
+ return cdrom_queue_packet_command(drive, &pc);
}
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
static int
-cdrom_lockdoor (ide_drive_t *drive, int lockflag,
- struct atapi_request_sense *reqbuf)
+cdrom_lockdoor(ide_drive_t *drive, int lockflag)
{
- struct atapi_request_sense my_reqbuf;
- int stat;
+ struct request_sense *sense;
struct packet_command pc;
-
- if (reqbuf == NULL)
- reqbuf = &my_reqbuf;
+ int stat;
/* If the drive cannot lock the door, just pretend. */
if (CDROM_CONFIG_FLAGS (drive)->no_doorlock)
stat = 0;
else {
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
-
+ memset(&pc, 0, sizeof(pc));
pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = (lockflag != 0);
stat = cdrom_queue_packet_command (drive, &pc);
}
+ sense = pc.sense_data;
+
/* If we got an illegal field error, the drive
probably cannot lock the door. */
if (stat != 0 &&
- reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->asc == 0x24 || reqbuf->asc == 0x20)) {
+ sense->sense_key == ILLEGAL_REQUEST &&
+ (sense->asc == 0x24 || sense->asc == 0x20)) {
printk ("%s: door locking not supported\n",
drive->name);
CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
}
/* no medium, that's alright. */
- if (stat != 0 && reqbuf->sense_key == NOT_READY && reqbuf->asc == 0x3a)
+ if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
stat = 0;
if (stat == 0)
/* Eject the disk if EJECTFLAG is 0.
If EJECTFLAG is 1, try to reload the disk. */
-static int
-cdrom_eject (ide_drive_t *drive, int ejectflag,
- struct atapi_request_sense *reqbuf)
+static int cdrom_eject(ide_drive_t *drive, int ejectflag)
{
struct packet_command pc;
- if (CDROM_CONFIG_FLAGS (drive)->no_eject && !ejectflag)
+ if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
return -EDRIVE_CANT_DO_THIS;
/* reload fails on some drives, if the tray is locked */
- if (CDROM_STATE_FLAGS (drive)->door_locked && ejectflag)
+ if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
return 0;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof (pc));
pc.c[0] = GPCMD_START_STOP_UNIT;
pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
-static int
-cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
{
struct {
__u32 lba;
int stat;
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof (pc));
pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
- pc.buflen = sizeof (capbuf);
+ pc.buflen = sizeof(capbuf);
- stat = cdrom_queue_packet_command (drive, &pc);
+ stat = cdrom_queue_packet_command(drive, &pc);
if (stat == 0)
*capacity = be32_to_cpu(capbuf.lba);
return stat;
}
-
-static int
-cdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,
- int format, char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
+ int format, char *buf, int buflen)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
pc.buffer = buf;
pc.buflen = buflen;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
pc.c[9] = (format << 6);
- if (msf_flag) pc.c[1] = 2;
+
+ if (msf_flag)
+ pc.c[1] = 2;
+
return cdrom_queue_packet_command (drive, &pc);
}
/* Try to read the entire TOC for the disk into our internal buffer. */
-static int
-cdrom_read_toc (ide_drive_t *drive, struct atapi_request_sense *reqbuf)
+static int cdrom_read_toc (ide_drive_t *drive)
{
int stat, ntracks, i;
struct cdrom_info *info = drive->driver_data;
/* Check to see if the existing data is still valid.
If it is, just return. */
if (CDROM_STATE_FLAGS (drive)->toc_valid)
- (void) cdrom_check_status (drive, NULL);
+ (void) cdrom_check_status(drive);
if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
/* First read just the header, so we know how long the TOC is. */
stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header), reqbuf);
+ sizeof (struct atapi_toc_header));
if (stat) return stat;
#if ! STANDARD_ATAPI
stat = cdrom_read_tocentry (drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr,
sizeof (struct atapi_toc_header) +
(ntracks + 1) *
- sizeof (struct atapi_toc_entry), reqbuf);
+ sizeof (struct atapi_toc_entry));
if (stat && toc->hdr.first_track > 1) {
/* Cds with CDI tracks only don't have any TOC entries,
0, (char *)&toc->hdr,
sizeof (struct atapi_toc_header) +
(ntracks+1) *
- sizeof (struct atapi_toc_entry),
- reqbuf);
+ sizeof (struct atapi_toc_entry));
if (stat) {
return stat;
}
if (toc->hdr.first_track != CDROM_LEADOUT) {
/* Read the multisession information. */
stat = cdrom_read_tocentry (drive, 0, 1, 1,
- (char *)&ms_tmp, sizeof (ms_tmp),
- reqbuf);
+ (char *)&ms_tmp, sizeof (ms_tmp));
if (stat) return stat;
} else {
ms_tmp.ent.addr.msf.minute = 0;
(long *)&toc->capacity);
if (stat)
#endif
- stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
+ stat = cdrom_read_capacity (drive, &toc->capacity);
if (stat) toc->capacity = 0x1fffff;
/* for general /dev/cdrom like mounting, one big disc */
}
-static int
-cdrom_read_subchannel (ide_drive_t *drive, int format,
- char *buf, int buflen,
- struct atapi_request_sense *reqbuf)
+static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
+ int buflen)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
- pc.buffer = buf;
+ pc.buffer = buf;
pc.buflen = buflen;
pc.c[0] = GPCMD_READ_SUBCHANNEL;
pc.c[1] = 2; /* MSF addressing */
pc.c[3] = format;
pc.c[7] = (buflen >> 8);
pc.c[8] = (buflen & 0xff);
- return cdrom_queue_packet_command (drive, &pc);
+ return cdrom_queue_packet_command(drive, &pc);
}
/* ATAPI cdrom drives are free to select the speed you request or any slower
rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int
-cdrom_select_speed (ide_drive_t *drive, int speed,
- struct atapi_request_sense *reqbuf)
+static int cdrom_select_speed (ide_drive_t *drive, int speed)
{
struct packet_command pc;
- memset (&pc, 0, sizeof (pc));
- pc.sense_data = reqbuf;
+ memset(&pc, 0, sizeof(pc));
if (speed == 0)
- speed = 0xffff; /* set to max */
+ speed = 0xffff; /* set to max */
else
- speed *= 177; /* Nx to kbytes/s */
+ speed *= 177; /* Nx to kbytes/s */
pc.c[0] = GPCMD_SET_SPEED;
/* Read Drive speed in kbytes/second MSB */
}
-static
-int cdrom_get_toc_entry (ide_drive_t *drive, int track,
- struct atapi_toc_entry **ent,
- struct atapi_request_sense *reqbuf)
+static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
+ struct atapi_toc_entry **ent)
{
struct cdrom_info *info = drive->driver_data;
struct atapi_toc *toc = info->toc;
memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
pc.buffer = cgc->buffer;
pc.buflen = cgc->buflen;
- return cgc->stat = cdrom_queue_packet_command(drive, &pc);
+ cgc->stat = cdrom_queue_packet_command(drive, &pc);
+
+ /* There was an error, assign sense. */
+ if (cgc->stat)
+ cgc->sense = pc.sense_data;
+
+ return cgc->stat;
}
static
struct atapi_toc *toc;
/* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc (drive, NULL);
+ stat = cdrom_read_toc(drive);
if (stat) return stat;
toc = info->toc;
struct cdrom_tocentry *tocentry = (struct cdrom_tocentry*) arg;
struct atapi_toc_entry *toce;
- stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce,
- NULL);
+ stat = cdrom_get_toc_entry (drive, tocentry->cdte_track, &toce);
if (stat) return stat;
tocentry->cdte_ctrl = toce->control;
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct atapi_request_sense rq;
if (position) {
- int stat = cdrom_lockdoor (drive, 0, &rq);
+ int stat = cdrom_lockdoor (drive, 0);
if (stat) return stat;
}
- return cdrom_eject (drive, !position, NULL);
+ return cdrom_eject(drive, !position);
}
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- return cdrom_lockdoor (drive, lock, NULL);
+ return cdrom_lockdoor (drive, lock);
}
static
{
int stat, attempts = 3;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct atapi_request_sense reqbuf;
struct cdrom_generic_command cgc;
struct {
char pad[8];
struct atapi_capabilities_page cap;
} buf;
- stat=cdrom_select_speed (drive, speed, &reqbuf);
- if (stat<0)
+
+ if ((stat = cdrom_select_speed (drive, speed)) < 0)
return stat;
init_cdrom_command(&cgc, &buf, sizeof(buf));
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct cdrom_info *info = drive->driver_data;
if (slot_nr == CDSL_CURRENT) {
-
- struct atapi_request_sense sense;
- int stat = cdrom_check_status (drive, &sense);
- if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
+ struct request_sense *sense = &info->sense_data;
+ int stat = cdrom_check_status(drive);
+ if (stat == 0 || sense->sense_key == UNIT_ATTENTION)
return CDS_DISC_OK;
- if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
- sense.ascq == 0x04)
+ if (sense->sense_key == NOT_READY && sense->asc == 0x04 &&
+ sense->ascq == 0x04)
return CDS_DISC_OK;
- if (sense.sense_key == NOT_READY) {
+ if (sense->sense_key == NOT_READY) {
/* ATAPI doesn't have anything that can help
us decide whether the drive is really
emtpy or the tray is just open. irk. */
char mcnbuf[24];
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- stat = cdrom_read_subchannel (drive, 2, /* get MCN */
- mcnbuf, sizeof (mcnbuf),
- NULL);
- if (stat) return stat;
+/* get MCN */
+ if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf))))
+ return stat;
memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
sizeof (mcn_info->medium_catalog_number)-1);
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
if (slot_nr == CDSL_CURRENT) {
- (void) cdrom_check_status (drive, NULL);
+ (void) cdrom_check_status(drive);
CDROM_STATE_FLAGS (drive)->media_changed = 0;
return CDROM_STATE_FLAGS (drive)->media_changed;
} else {
* Copyright (C) 1998, 1999 Jens Axboe
*/
+#include <linux/cdrom.h>
#include <asm/byteorder.h>
/* Turn this on to have the driver print out the meanings of the
__u8 reserved : 4;
byte current_speed; /* Current speed of the drive */
};
-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
-
-struct atapi_request_sense {
-#if defined(__BIG_ENDIAN_BITFIELD)
- unsigned char valid : 1;
- unsigned char error_code : 7;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned char error_code : 7;
- unsigned char valid : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- byte reserved1;
-#if defined(__BIG_ENDIAN_BITFIELD)
- unsigned char reserved3 : 2;
- unsigned char ili : 1;
- unsigned char reserved2 : 1;
- unsigned char sense_key : 4;
-#elif defined(__LITTLE_ENDIAN_BITFIELD)
- unsigned char sense_key : 4;
- unsigned char reserved2 : 1;
- unsigned char ili : 1;
- unsigned char reserved3 : 2;
-#else
-#error "Please fix <asm/byteorder.h>"
-#endif
- byte info[4];
- byte sense_len;
- byte command_info[4];
- byte asc;
- byte ascq;
- byte fru;
- byte sense_key_specific[3];
-};
+#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
struct packet_command {
char *buffer;
int buflen;
int stat;
- struct atapi_request_sense *sense_data;
+ struct request_sense *sense_data;
unsigned char c[12];
};
/* The result of the last successful request sense command
on this device. */
- struct atapi_request_sense sense_data;
+ struct request_sense sense_data;
struct request request_sense_request;
struct packet_command request_sense_pc;
V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
Adaption to linux kernel > 2.1.0
Werner Zimmermann, Nov 29, 97
+
+ November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ Removed init_module & cleanup_module in favor of
+ module_init & module_exit.
+ Torben Mathiasen <tmm@image.dk>
*/
#include <linux/version.h>
static int aztGetToc(int multi);
/* Kernel Interface Functions */
-void aztcd_setup(char *str, int *ints);
static int check_aztcd_media_change(kdev_t full_dev);
static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
static void azt_transfer(void);
static int aztcd_release(struct inode * inode, struct file * file);
#endif
-int aztcd_init(void);
-#ifdef MODULE
- int init_module(void);
- void cleanup_module(void);
-#endif MODULE
+int aztcd_init(void);
+
static struct file_operations azt_fops = {
NULL, /* lseek - default */
block_read, /* read - general block-dev read */
Kernel Interface Functions
##########################################################################
*/
-#ifdef AZT_KERNEL_PRIOR_2_1
-void aztcd_setup(char *str, int *ints)
-#else
-void __init aztcd_setup(char *str, int *ints)
-#endif
-{ if (ints[0] > 0)
- azt_port = ints[1];
- if (ints[0] > 1)
- azt_cont = ints[2];
+
+#ifndef MODULE
+static int __init aztcd_setup(char *str)
+{
+ int ints[4];
+
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
+
+ if (ints[0] > 0)
+ azt_port = ints[1];
+ if (ints[1] > 1)
+ azt_cont = ints[2];
+ return 1;
}
+__setup("aztcd=", aztcd_setup);
+
+#endif /* !MODULE */
+
/*
* Checking if the media has been changed
*/
* Test for presence of drive and initialize it. Called at boot time.
*/
-#ifdef AZT_KERNEL_PRIOR_2_1
-int aztcd_init(void)
-#else
int __init aztcd_init(void)
-#endif
{ long int count, max_count;
unsigned char result[50];
int st;
return (0);
}
-#ifdef MODULE
-
-int init_module(void)
-{
- return aztcd_init();
-}
-
-void cleanup_module(void)
+void __exit aztcd_exit(void)
{
if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL))
{ printk("What's that: can't unregister aztcd\n");
release_region(azt_port,4); /*proprietary interface*/
printk(KERN_INFO "aztcd module released.\n");
}
-#endif MODULE
+#ifdef MODULE
+module_init(aztcd_init);
+#endif
+module_exit(aztcd_exit);
/*##########################################################################
Aztcd State Machine: Controls Drive Operating State
static int azt_bcd2bin(unsigned char bcd)
{ return (bcd >> 4) * 10 + (bcd & 0xF);
}
-
-
-- Added setup of write mode for packet writing.
-- Fixed CDDA ripping with cdda2wav - accept much larger requests of
number of frames and split the reads in blocks of 8.
+
+ 3.05 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
+ -- Added support for changing the region of DVD drives.
+ -- Added sense data to generic command.
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 3.05"
-#define VERSION "Id: cdrom.c 3.05 1999/10/24"
+#define REVISION "Revision: 3.06"
+#define VERSION "Id: cdrom.c 3.06 1999/12/13"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
cgc.cmd[5] = entry.cdte_addr.msf.frame;
entry.cdte_track = ti.cdti_trk1;
- if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
+ if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
return -EINVAL;
cgc.cmd[6] = entry.cdte_addr.msf.minute;
case CDROM_SEND_PACKET: {
__u8 *userbuf, copy = 0;
+ struct request_sense *sense;
if (!CDROM_CAN(CDC_GENERIC_PACKET))
return -ENOSYS;
cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n");
copy = !!cgc.buflen;
userbuf = cgc.buffer;
cgc.buffer = NULL;
+ sense = cgc.sense;
if (userbuf != NULL && copy) {
/* usually commands just copy data one way, i.e.
* we send a buffer to the drive and the command
ret = cdo->generic_packet(cdi, &cgc);
if (copy && !ret)
__copy_to_user(userbuf, cgc.buffer, cgc.buflen);
+ /* copy back sense data */
+ if (ret && sense != NULL)
+ if (copy_to_user(sense, cgc.sense, sizeof(struct request_sense)))
+ ret = -EFAULT;
kfree(cgc.buffer);
return ret;
}
* <kodis@jagunet.com>. Work begun on fixing driver to
* work under 2.1.X. Added temporary extra printks
* which seem to slow it down enough to work.
+ *
+ * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
*/
#include <linux/major.h>
#ifndef MODULE
/*
* Set up base I/O and interrupts, called from main.c.
+
*/
-void __init
-cdu31a_setup(char *strings,
- int *ints)
+
+static int __init cdu31a_setup(char *strings)
{
+ int ints[4];
+
+ (void)get_options(strings, ARRAY_SIZE(ints), ints);
+
if (ints[0] > 0)
{
cdu31a_port = ints[1];
printk("CDU31A: Unknown interface type: %s\n", strings);
}
}
+
+ return 1;
}
+
+__setup("cdu31a=", cdu31a_setup);
+
#endif
static int cdu31a_block_size;
return -EIO;
}
-#ifdef MODULE
-int
-init_module(void)
-{
- return cdu31a_init();
-}
-
-void
-cleanup_module(void)
+void __exit
+cdu31a_exit(void)
{
if (unregister_cdrom(&scd_info))
{
release_region(cdu31a_port,4);
printk(KERN_INFO "cdu31a module released.\n");
}
-#endif MODULE
+
+#ifdef MODULE
+module_init(cdu31a_init);
+#endif
+module_exit(cdu31a_exit);
+
24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
code. The Uniform CDROM driver now provides this functionality.
+
+9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x
+ Removed init_module & cleanup_module in favor of
+ module_init & module_exit.
+ Torben Mathiasen <tmm@image.dk>
*
* Parts of the code are based upon lmscd.c written by Kai Petzke,
* sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
}
}
-int init_module(void)
+int __cm206_init(void)
{
parse_options();
#if !defined(AUTO_PROBE_MODULE)
return cm206_init();
}
-void cleanup_module(void)
+void __exit cm206_exit(void)
{
cleanup(4);
printk(KERN_INFO "cm206 removed\n");
}
+
+module_init(__cm206_init);
+module_exit(cm206_exit);
#else /* !MODULE */
/* This setup function accepts either `auto' or numbers in the range
* 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-void __init cm206_setup(char *s, int *p)
+
+static int __init cm206_setup(char *s)
{
- int i;
+ int i, p[4];
+
+ (void)get_options(s, ARRAY_SIZE(p), p);
+
if (!strcmp(s, "auto")) auto_probe=1;
for(i=1; i<=p[0]; i++) {
if (0x300 <= p[i] && i<= 0x370 && p[i] % 0x10 == 0) {
auto_probe = 0;
}
}
+ return 1;
}
-#endif /* MODULE */
+
+__setup("cm206=", cm206_setup);
+
+#endif /* !MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -D__SMP__ -pipe -fno-strength-reduce -m486 -DCPU=486 -D__SMP__ -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cm206.o cm206.c"
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ --------------------------------------------------------------------
+
+ 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ Removed init_module & cleanup_module in favor of
+ module_init & module_exit.
+ Torben Mathiasen <tmm@image.dk>
*/
}
-void __init gscd_setup (char *str, int *ints)
+#ifndef MODULE
+/* Using new interface for kernel-parameters */
+
+static int __init gscd_setup (char *str)
{
+ int ints[2];
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
+
if (ints[0] > 0)
{
gscd_port = ints[1];
}
+ return 1;
}
+__setup("gscd=", gscd_setup);
+
+#endif
static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
{
}
#endif
-#ifdef MODULE
/* Init for the Module-Version */
-int init_module (void)
+int init_gscd(void)
{
long err;
}
}
-void cleanup_module (void)
+void __exit exit_gscd(void)
{
if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL))
release_region (gscd_port,4);
printk(KERN_INFO "GoldStar-module released.\n" );
}
-#endif
+
+#ifdef MODULE
+module_init(init_gscd);
+#endif
+module_exit(exit_gscd);
/* Test for presence of drive and initialize it. Called only at boot time. */
* Removed sound configuration.
* Added "module" support.
*
+ * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
+ *
* Detect cdrom interface on ISP16 sound card.
* Configure cdrom interface.
*
MODULE_PARM(isp16_cdrom_irq, "i");
MODULE_PARM(isp16_cdrom_dma, "i");
MODULE_PARM(isp16_cdrom_type, "s");
-int init_module(void);
-void cleanup_module(void);
+void isp16_exit(void);
#endif
#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
+#ifndef MODULE
-void __init
-isp16_setup(char *str, int *ints)
+static int
+__init isp16_setup(char *str)
{
+ int ints[4];
+
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
if ( ints[0] > 0 )
isp16_cdrom_base = ints[1];
if ( ints[0] > 1 )
isp16_cdrom_dma = ints[3];
if ( str )
isp16_cdrom_type = str;
+
+ return 1;
}
+__setup("isp16=", isp16_setup);
+
+#endif /* MODULE */
+
/*
* ISP16 initialisation.
*
return(0);
}
-#ifdef MODULE
-int init_module(void)
-{
- return isp16_init();
-}
-
-void cleanup_module(void)
+void __exit isp16_exit(void)
{
release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
printk(KERN_INFO "ISP16: module released.\n");
}
-#endif /* MODULE */
+
+#ifdef MODULE
+module_init(isp16_init);
+#endif
+module_exit(isp16_exit);
+
+
#define ISP16_IO_BASE 0xF8D
#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */
-void isp16_setup(char *str, int *ints);
int isp16_init(void);
November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
+
+ November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ Removed init_module & cleanup_module in favor of
+ module_init & module_exit.
+ Torben Mathiasen <tmm@image.dk>
+
+
*/
#include <linux/module.h>
"mcd", /* name of the device type */
};
-
-void __init mcd_setup(char *str, int *ints)
+#ifndef MODULE
+static int __init mcd_setup(char *str)
{
+ int ints[9];
+
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
+
if (ints[0] > 0)
mcd_port = ints[1];
if (ints[0] > 1)
if (ints[0] > 2)
mitsumi_bug_93_wait = ints[3];
#endif /* WORK_AROUND_MITSUMI_BUG_93 */
+
+ return 1;
}
+__setup("mcd=", mcd_setup);
+
+#endif /* MODULE */
static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
{
/* This routine gets called during initialization if things go wrong,
- * and is used in cleanup_module as well. */
+ * and is used in mcd_exit as well. */
static void cleanup(int level)
{
switch (level) {
return limit > 0 ? 0 : -1;
}
-#ifdef MODULE
-int init_module(void)
-{
- return mcd_init();
-}
-void cleanup_module(void)
+void __exit mcd_exit(void)
{
cleanup(3);
}
-#endif MODULE
+
+#ifdef MODULE
+module_init(mcd_init);
+#endif
+module_exit(mcd_exit);
+
+
* Marcin Dalecki (improved performance, shortened code)
* ... somebody forgotten?
*
+ * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
*/
int mcdx_init(void);
void do_mcdx_request(request_queue_t * q);
-/* already declared in init/main */
-void mcdx_setup(char *, int *);
/* Indirect exported functions. These functions are exported by their
addresses, such as mcdx_open and mcdx_close in the
return 1;
}
-void __init mcdx_setup(char *str, int *pi)
+#ifndef MODULE
+static int __init mcdx_setup(char *str)
{
+ int pi[4];
+ (void)get_options(str, ARRAY_SIZE(pi), pi);
+
if (pi[0] > 0) mcdx_drive_map[0][0] = pi[1];
if (pi[0] > 1) mcdx_drive_map[0][1] = pi[2];
+ return 1;
}
+__setup("mcdx=", mcdx_setup);
+
+#endif
+
/* DIRTY PART ******************************************************/
static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
}
/* MODULE STUFF ***********************************************************/
-#ifdef MODULE
+
EXPORT_NO_SYMBOLS;
-int init_module(void)
+int __mcdx_init(void)
{
int i;
int drives = 0;
return 0;
}
-void cleanup_module(void)
+void __exit mcdx_exit(void)
{
int i;
#endif
}
-#endif MODULE
+#ifdef MODULE
+module_init(__mcdx_init);
+#endif
+module_exit(mcdx_exit);
+
/* Support functions ************************************************/
thanks to Luke McFarlane. Also tidied up some
printk behaviour. ISP16 initialization
is now handled by a separate driver.
+
+ 09-11-99 Make kernel-parameter implementation work with 2.3.x
+ Removed init_module & cleanup_module in favor of
+ module_init & module_exit.
+ Torben Mathiasen <tmm@image.dk>
*/
\f
/* Includes */
NULL /* revalidate */
};
-
+#ifndef MODULE
/* Get kernel parameter when used as a kernel driver */
-void __init optcd_setup(char *str, int *ints)
+static int optcd_setup(char *str)
{
+ int ints[4];
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
+
if (ints[0] > 0)
optcd_port = ints[1];
+
+ return 1;
}
+__setup("optcd=", optcd_setup);
+
+#endif MODULE
+
/* Test for presence of drive and initialize it. Called at boot time
or during module initialisation. */
int __init optcd_init(void)
}
-#ifdef MODULE
-int init_module(void)
-{
- return optcd_init();
-}
-
-
-void cleanup_module(void)
+void __exit optcd_exit(void)
{
if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
printk(KERN_ERR "optcd: what's that: can't unregister\n");
release_region(optcd_port, 4);
printk(KERN_INFO "optcd: module released.\n");
}
-#endif MODULE
+
+#ifdef MODULE
+module_init(optcd_init);
+#endif
+module_exit(optcd_exit);
+
+
* 4.62 Fix a bug where playing audio left the drive in an unusable state.
* Heiko Eissfeldt <heiko@colossus.escape.de>
*
+ * November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
+ *
*
* TODO
* implement "read all subchannel data" (96 bytes per frame)
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
* bytes above).
*
*/
+
#if (SBPCD_ISSUE-1)
-static void __init sbpcd_setup(const char *s, int *p)
+static int sbpcd_setup(char *s)
#else
-void __init sbpcd_setup(const char *s, int *p)
+int sbpcd_setup(char *s)
#endif
{
+ int p[4];
+ (void)get_options(s, ARRAY_SIZE(p), p);
setup_done++;
msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
sbpro_type=0; /* default: "LaserMate" */
}
}
else CDi_data=sbpcd_ioaddr+2;
+
+ return 1;
}
+
+__setup("sbpcd=", sbpcd_setup);
+
+
/*==========================================================================*/
/*
* Sequoia S-1000 CD-ROM Interface Configuration
* Called once at boot or load time.
*/
#ifdef MODULE
-int init_module(void)
+int __init __SBPCD_INIT(void)
#else
int __init SBPCD_INIT(void)
#endif MODULE
else if (sbpcd[port_index+1]==1) type=str_sb;
else if (sbpcd[port_index+1]==3) type=str_t16;
else type=str_lm;
- sbpcd_setup(type, addr);
+ sbpcd_setup((char *)type);
#if DISTRIBUTION
msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
#endif DISTRIBUTION
}
/*==========================================================================*/
#ifdef MODULE
-void cleanup_module(void)
+void sbpcd_exit(void)
{
int j;
}
msg(DBG_INF, "%s module released.\n", major_name);
}
+
+
+#ifdef MODULE
+module_init(__SBPCD_INIT) /*HACK!*/;
+#endif
+module_exit(sbpcd_exit);
+
+
#endif MODULE
/*==========================================================================*/
/*
* the previous version of this driver. Coded added by Anthony Barbachan
* from bugfix tip originally suggested by Alan Cox.
*
+ * November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
*/
#define SJCD_VERSION_MAJOR 1
* Set up device, i.e., use command line data to set
* base address.
*/
-void __init sjcd_setup( char *str, int *ints )
+#ifndef MODULE
+static int __init sjcd_setup( char *str)
{
+ int ints[2];
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0)
sjcd_base = ints[1];
+
+ return 1;
}
+__setup("sjcd=", sjcd_setup);
+
+#endif
+
/*
* Special converters.
*/
return(0);
}
-#ifdef MODULE
-
-int init_module(void)
-{
- return sjcd_init();
-}
-void cleanup_module(void)
+void __exit sjcd_exit(void)
{
if ( sjcd_cleanup() )
printk( "SJCD: module: cannot be removed.\n" );
else
printk(KERN_INFO "SJCD: module: removed.\n");
}
+
+#ifdef MODULE
+module_init(sjcd_init);
#endif
+module_exit(sjcd_exit);
+
+
* More changes to support CDU-510/515 series
* (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
*
+ * November 1999 -- Make kernel-parameter implementation work with 2.3.x
+ * Removed init_module & cleanup_module in favor of
+ * module_init & module_exit.
+ * Torben Mathiasen <tmm@image.dk>
+ *
* Things to do:
* - handle errors and status better, put everything into a single word
* - use interrupts (code mostly there, but a big hole still missing)
}
#ifndef MODULE
+
/*
* accept "kernel command line" parameters
* (added by emoenke@gwdg.de)
*
* the address value has to be the existing CDROM port address.
*/
-void __init
-sonycd535_setup(char *strings, int *ints)
+static int __init
+sonycd535_setup(char *strings)
{
+ int ints[3];
+ (void)get_options(strings, ARRAY_SIZE(ints), ints);
/* if IRQ change and default io base desired,
* then call with io base of 0
*/
if ((strings != NULL) && (*strings != '\0'))
printk(CDU535_MESSAGE_NAME
": Warning: Unknown interface type: %s\n", strings);
+
+ return 1;
}
-#else /* MODULE */
+__setup("sonycd535=", sonycd535_setup);
-int init_module(void)
-{
- return sony535_init();
-}
+#endif /* MODULE */
-void
-cleanup_module(void)
+void __exit
+sony535_exit(void)
{
int i;
else
printk(KERN_INFO CDU535_HANDLE " module released\n");
}
-#endif /* MODULE */
+
+#ifdef MODULE
+module_init(sony535_init);
+#endif
+module_exit(sony535_exit);
+
+
fi
endmenu
-bool 'Direct Rendering Manager (XFree86 DRI support) (EXPERIMENTAL)' CONFIG_DRM
+bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
dep_tristate ' 3dfx Banshee/Voodoo3' CONFIG_DRM_TDFX $CONFIG_DRM
if [ "$CONFIG_DRM" = "y" ]; then
dep_tristate ' 3dlabs GMX 2000' CONFIG_DRM_GAMMA m
#ifndef _AGP_BACKEND_PRIV_H
#define _AGP_BACKEND_PRIV_H 1
+#include <linux/config.h>
+
enum aper_size_type {
U8_APER_SIZE,
U16_APER_SIZE,
#include <linux/miscdevice.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <asm/io.h>
#include <asm/page.h>
{"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST},
{"HITACHI", "GF-1050","*", BLIST_GHOST}, /* Hitachi SCSI DVD-RAM */
{"TOSHIBA","CDROM","*", BLIST_ISROM},
+ {"Toshiba","DVD-RAM SD-W1101","*", BLIST_GHOST},
+ {"Toshiba","DVD-RAM SD-W1111","*", BLIST_GHOST},
/*
* Must be at end of list...
struct request request; /* A copy of the command we are
working on */
- unsigned char sense_buffer[64]; /* obtained by REQUEST SENSE when
- CHECK CONDITION is received on
- original command (auto-sense) */
+ unsigned char sense_buffer[64]; /* obtained by REQUEST SENSE
+ * when CHECK CONDITION is
+ * received on original command
+ * (auto-sense) */
unsigned flags;
* anything out of the ordinary is seen.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
*/
#define __NO_VERSION__
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
- if (((this_count > 0xff) || (block > 0x1fffff)) && SCpnt->device->ten) {
+ if (((this_count > 0xff) || (block > 0x1fffff)) || SCpnt->device->ten) {
if (this_count > 0xffff)
this_count = 0xffff;
return -EROFS;
}
/*
- * It is possible that the disk changing stuff resulted in the device being taken
- * offline. If this is the case, report this to the user, and don't pretend that
+ * It is possible that the disk changing stuff resulted in the device
+ * being taken offline. If this is the case, report this to the user,
+ * and don't pretend that
* the open actually succeeded.
*/
if (!rscsi_disks[target].device->online) {
/*
Handle MEDIUM ERRORs that indicate partial success. Since this is a
- relatively rare error condition, no care is taken to avoid unnecessary
- additional work such as memcpy's that could be avoided.
+ relatively rare error condition, no care is taken to avoid
+ unnecessary additional work such as memcpy's that could be avoided.
*/
- if (driver_byte(result) != 0 && /* An error occurred */
- SCpnt->sense_buffer[0] == 0xF0 && /* Sense data is valid */
- SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
- long error_sector = (SCpnt->sense_buffer[3] << 24) |
- (SCpnt->sense_buffer[4] << 16) |
- (SCpnt->sense_buffer[5] << 8) |
- SCpnt->sense_buffer[6];
- if (SCpnt->request.bh != NULL)
- block_sectors = SCpnt->request.bh->b_size >> 9;
- switch (SCpnt->device->sector_size) {
- case 1024:
- error_sector <<= 1;
- if (block_sectors < 2)
- block_sectors = 2;
- break;
- case 2048:
- error_sector <<= 2;
- if (block_sectors < 4)
- block_sectors = 4;
- break;
- case 256:
- error_sector >>= 1;
- break;
- default:
- break;
+ /* An error occurred */
+ if (driver_byte(result) != 0) {
+ /* Sense data is valid */
+ if (SCpnt->sense_buffer[0] == 0xF0 && SCpnt->sense_buffer[2] == MEDIUM_ERROR) {
+ long error_sector = (SCpnt->sense_buffer[3] << 24) |
+ (SCpnt->sense_buffer[4] << 16) |
+ (SCpnt->sense_buffer[5] << 8) |
+ SCpnt->sense_buffer[6];
+ if (SCpnt->request.bh != NULL)
+ block_sectors = SCpnt->request.bh->b_size >> 9;
+ switch (SCpnt->device->sector_size) {
+ case 1024:
+ error_sector <<= 1;
+ if (block_sectors < 2)
+ block_sectors = 2;
+ break;
+ case 2048:
+ error_sector <<= 2;
+ if (block_sectors < 4)
+ block_sectors = 4;
+ break;
+ case 256:
+ error_sector >>= 1;
+ break;
+ default:
+ break;
+ }
+ error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+ error_sector &= ~(block_sectors - 1);
+ good_sectors = error_sector - SCpnt->request.sector;
+ if (good_sectors < 0 || good_sectors >= this_count)
+ good_sectors = 0;
+ }
+ if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {
+ if (SCpnt->device->ten == 1) {
+ if (SCpnt->cmnd[0] == READ_10 ||
+ SCpnt->cmnd[0] == WRITE_10)
+ SCpnt->device->ten = 0;
+ }
}
- error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
- error_sector &= ~(block_sectors - 1);
- good_sectors = error_sector - SCpnt->request.sector;
- if (good_sectors < 0 || good_sectors >= this_count)
- good_sectors = 0;
}
/*
* This calls the generic completion function, now that we know
return 0;
/*
- * If the device is offline, don't send any commands - just pretend as if
- * the command failed. If the device ever comes back online, we can deal with
- * it then. It is only because of unrecoverable errors that we would ever
- * take a device offline in the first place.
+ * If the device is offline, don't send any commands - just pretend as
+ * if the command failed. If the device ever comes back online, we
+ * can deal with it then. It is only because of unrecoverable errors
+ * that we would ever take a device offline in the first place.
*/
if (rscsi_disks[target].device->online == FALSE) {
rscsi_disks[target].ready = 0;
*/
retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);
- if (retval) { /* Unable to test, unit probably not ready. This usually
- * means there is no disc in the drive. Mark as changed,
- * and we will figure it out later once the drive is
- * available again. */
+ if (retval) { /* Unable to test, unit probably not ready.
+ * This usually means there is no disc in the
+ * drive. Mark as changed, and we will figure
+ * it out later once the drive is available
+ * again. */
rscsi_disks[target].ready = 0;
rscsi_disks[target].device->changed = 1;
}
spintime = 1;
spintime_value = jiffies;
- time1 = jiffies + HZ;
- while (time_before(jiffies, time1)); /* Wait 1 second for next try */
+ time1 = HZ;
+ /* Wait 1 second for next try */
+ do {
+ current->state = TASK_UNINTERRUPTIBLE;
+ time1 = schedule_timeout(time1);
+ } while(time1);
printk(".");
}
} while (the_result && spintime && time_after(spintime_value + 100 * HZ, jiffies));
static request_queue_t *sr_find_queue(kdev_t dev)
{
- if (MINOR(dev) >= sr_template.dev_max
- || !scsi_CDs[MINOR(dev)].device)
- return NULL; /* No such device */
+ /*
+ * No such device
+ */
+ if (MINOR(dev) >= sr_template.dev_max || !scsi_CDs[MINOR(dev)].device)
+ return NULL;
+
return &scsi_CDs[MINOR(dev)].device->request_queue;
}
SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.nr_sectors);
return 0;
}
- SCpnt->cmnd[0] = WRITE_6;
+ SCpnt->cmnd[0] = WRITE_10;
break;
case READ:
- SCpnt->cmnd[0] = READ_6;
+ SCpnt->cmnd[0] = READ_10;
break;
default:
- panic("Unknown sd command %d\n", SCpnt->request.cmd);
+ panic("Unknown sr command %d\n", SCpnt->request.cmd);
}
SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
SCpnt->cmnd[1] = (SCpnt->lun << 5) & 0xe0;
- if (((this_count > 0xff) || (block > 0x1fffff)) && SCpnt->device->ten) {
- if (this_count > 0xffff)
- this_count = 0xffff;
-
- SCpnt->cmnd[0] += READ_10 - READ_6;
- SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
- SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
- SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
- SCpnt->cmnd[5] = (unsigned char) block & 0xff;
- SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
- SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
- SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
- } else {
- if (this_count > 0xff)
- this_count = 0xff;
-
- SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
- SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
- SCpnt->cmnd[3] = (unsigned char) block & 0xff;
- SCpnt->cmnd[4] = (unsigned char) this_count;
- SCpnt->cmnd[5] = 0;
- }
+ if (this_count > 0xffff)
+ this_count = 0xffff;
+
+ SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
+ SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
+ SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
+ SCpnt->cmnd[5] = (unsigned char) block & 0xff;
+ SCpnt->cmnd[6] = SCpnt->cmnd[9] = 0;
+ SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
+ SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
/*
* We shouldn't disconnect in the middle of a sector, so with a dumb
Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
unsigned char *buffer = cgc->buffer;
int buflen;
- int stat;
/* get the device */
SCpnt = scsi_allocate_device(device, 1);
scsi_wait_cmd(SCpnt, (void *) cgc->cmd, (void *) buffer, cgc->buflen,
sr_init_done, SR_TIMEOUT, MAX_RETRIES);
- stat = SCpnt->result;
+ if ((cgc->stat = SCpnt->result))
+ cgc->sense = (struct request_sense *) SCpnt->sense_buffer;
/* release */
SCpnt->request.rq_dev = MKDEV(0, 0);
memcpy(cgc->buffer, buffer, cgc->buflen);
scsi_free(buffer, buflen);
}
- return stat;
+
+
+ return cgc->stat;
}
static int sr_registered = 0;
Scsi_Cmnd *SCpnt;
Scsi_Device *SDev;
int result, err = 0, retries = 0;
- unsigned long flags;
char *bounce_buffer;
SDev = scsi_CDs[target].device;
MOD_IN_SUB_DIRS :=
ALL_SUB_DIRS :=
+O_TARGET := video.o
+O_OBJS :=
+M_OBJS :=
+# This is a nice idea but needs depmod altering
+# MOD_LIST_NAME := VIDEO_MODULES
+
# All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o
obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+
+multi-y := $(filter $(list-multi), $(obj-y))
+multi-m := $(filter $(list-multi), $(obj-m))
+int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
# Files that are both resident and modular: remove from modular.
obj-m := $(filter-out $(obj-y), $(obj-m))
+int-m := $(filter-out $(int-y), $(int-m))
# Take multi-part drivers out of obj-y and put components in.
-obj-y := $(filter-out $(list-multi), $(obj-y))
+obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
# Translate to Rules.make lists.
-L_TARGET := video.a
-# This is a nice idea but needs depmod altering
-#MOD_LIST_NAME := VIDEO_MODULES
-
-L_OBJS := $(sort $(filter-out $(export-objs), $(obj-y)))
-LX_OBJS := $(sort $(filter $(export-objs), $(obj-y)))
+O_OBJS := $(filter-out $(export-objs), $(obj-y))
+OX_OBJS := $(filter $(export-objs), $(obj-y))
M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
+MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
include $(TOPDIR)/Rules.make
+clean:
+ rm -f core *.o *.a *.s
+
promcon_tbl.c: prom.uni ../char/conmakehash
../char/conmakehash prom.uni | \
sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
*/
#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/affs_fs.h>
#include <linux/amigaffs.h>
-#include <asm/uaccess.h>
+#include <linux/pagemap.h>
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-static int affs_readlink(struct dentry *, char *, int);
-static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int);
-
-struct inode_operations affs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- affs_readlink, /* readlink */
- affs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static int
-affs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int affs_symlink_readpage(struct dentry *dentry, struct page *page)
{
+ struct buffer_head *bh;
struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- struct slink_front *lf;
- int i, j;
- char c;
- char lc;
- char *pf;
-
- pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
-
- bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
- if (!bh) {
- affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
- inode->i_ino);
- return -EIO;
- }
- lf = (struct slink_front *)bh->b_data;
- lc = 0;
- i = 0;
- j = 0;
- pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
-
- if (strchr(lf->symname,':')) { /* Handle assign or volume name */
- while (i < buflen && (c = pf[i])) {
- put_user(c,buffer++);
- i++;
- }
- while (i < buflen && (c = lf->symname[j]) != ':') {
- put_user(c,buffer++);
- i++, j++;
- }
- if (i < buflen) {
- put_user('/',buffer++);
- i++, j++;
- }
- lc = '/';
- }
- while (i < buflen && (c = lf->symname[j])) {
- if (c == '/' && lc == '/' && (i + 3 < buflen)) { /* parent dir */
- put_user('.',buffer++);
- put_user('.',buffer++);
- i += 2;
- }
- put_user(c,buffer++);
- lc = c;
- i++, j++;
- }
- affs_brelse(bh);
- return i;
-}
-
-static struct dentry *
-affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- struct slink_front *lf;
- char *buffer;
+ char *link = (char*)kmap(page);
+ struct slink_front *lf;
+ int err;
int i, j;
char c;
char lc;
pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
- if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
- dput(base);
- return ERR_PTR(-ENOSPC);
- }
+ err = -EIO;
bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
- if (!bh) {
- affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
- inode->i_ino);
- kfree(buffer);
- dput(base);
- return ERR_PTR(-EIO);
- }
+ if (!bh)
+ goto fail;
i = 0;
j = 0;
lf = (struct slink_front *)bh->b_data;
lc = 0;
pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
- if (strchr(lf->symname,':')) { /* Handle assign or volume name */
+ if (strchr(lf->symname,':')) { /* Handle assign or volume name */
while (i < 1023 && (c = pf[i]))
- buffer[i++] = c;
+ link[i++] = c;
while (i < 1023 && lf->symname[j] != ':')
- buffer[i++] = lf->symname[j++];
+ link[i++] = lf->symname[j++];
if (i < 1023)
- buffer[i++] = '/';
+ link[i++] = '/';
j++;
lc = '/';
}
while (i < 1023 && (c = lf->symname[j])) {
if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
- buffer[i++] = '.';
- buffer[i++] = '.';
+ link[i++] = '.';
+ link[i++] = '.';
}
- buffer[i++] = c;
+ link[i++] = c;
lc = c;
j++;
}
- buffer[i] = '\0';
+ link[i] = '\0';
affs_brelse(bh);
- base = lookup_dentry(buffer,base,follow);
- kfree(buffer);
- return base;
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
}
+struct inode_operations affs_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: affs_symlink_readpage,
+};
*/
#include <linux/string.h>
-#include <linux/malloc.h>
#include <linux/efs_fs.h>
+#include <linux/pagemap.h>
-static int efs_readlink(struct dentry *, char *, int);
-static struct dentry * efs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-struct inode_operations efs_symlink_inode_operations = {
- NULL, /* no symlink file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- efs_readlink, /* readlink */
- efs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-static char *efs_linktarget(struct inode *in, int *len) {
- char *name;
+static int efs_symlink_readpage(struct dentry *dentry, struct page *page)
+{
+ char *link = (char*)kmap(page);
struct buffer_head * bh;
- efs_block_t size = in->i_size;
-
- if (size > 2 * EFS_BLOCKSIZE) {
- printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size);
- return NULL;
- }
+ struct inode * inode = dentry->d_inode;
+ efs_block_t size = inode->i_size;
+ int err;
- if (!(name = kmalloc(size + 1, GFP_KERNEL)))
- return NULL;
+ err = -ENAMETOOLONG;
+ if (size > 2 * EFS_BLOCKSIZE)
+ goto fail;
/* read first 512 bytes of link target */
- bh = bread(in->i_dev, efs_bmap(in, 0), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 0));
- return NULL;
- }
-
- memcpy(name, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
+ err = -EIO;
+ bh = bread(inode->i_dev, efs_bmap(inode, 0), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
brelse(bh);
-
if (size > EFS_BLOCKSIZE) {
- bh = bread(in->i_dev, efs_bmap(in, 1), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 1));
- return NULL;
- }
- memcpy(name + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
+ bh = bread(inode->i_dev, efs_bmap(inode, 1), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
brelse(bh);
}
-
- name[size] = (char) 0;
- if (len) *len = size;
-
- return name;
-}
-
-static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
- char *name;
- struct inode *inode = dentry->d_inode;
-
- if (!(name = efs_linktarget(inode, NULL))) {
- dput(base);
- return ERR_PTR(-ELOOP);
- }
- base = lookup_dentry(name, base, follow);
- kfree(name);
-
- return base;
-}
-
-static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) {
- int rc;
- char *name;
- struct inode *inode = dir->d_inode;
-
- if (!(name = efs_linktarget(inode, &bufsiz))) return 0;
- rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz;
- kfree(name);
-
- return rc;
+ link[size] = '\0';
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
}
+struct inode_operations efs_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: efs_symlink_readpage
+};
hpfs_ea_write(s, a, ano, 0, size, data);
}
-/* Read an extended attribute named 'key' */
+/* Read an extended attribute named 'key' into the provided buffer */
+int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
+ char *buf, int size)
+{
+ unsigned pos;
+ int ano, len;
+ secno a;
+ struct extended_attribute *ea;
+ struct extended_attribute *ea_end = fnode_end_ea(fnode);
+ for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ memcpy(buf, ea_data(ea), ea->valuelen);
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ a = fnode->ea_secno;
+ len = fnode->ea_size_l;
+ ano = fnode->ea_anode;
+ pos = 0;
+ while (pos < len) {
+ char ex[4 + 255 + 1 + 8];
+ ea = (struct extended_attribute *)ex;
+ if (pos + 4 > len) {
+ hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
+ ano ? "anode" : "sectors", a, len);
+ return -EIO;
+ }
+ if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
+ if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
+ return -EIO;
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
+ return -EIO;
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ pos += ea->namelen + ea->valuelen + 5;
+ }
+ return -ENOENT;
+indirect:
+ if (ea_len(ea) >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
+ return -EIO;
+ buf[ea_len(ea)] = 0;
+ return 0;
+}
+
+/* Read an extended attribute named 'key' */
char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
{
char *ret;
pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
while (pgpos < page->index) {
status = -ENOMEM;
- new_page = grab_page_cache(&inode->i_data, pgpos);
+ new_page = grab_cache_page(&inode->i_data, pgpos);
if (!new_page)
goto out;
status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
/* ea.c */
void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
+int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino);
-/* mmap.c */
-
-int hpfs_mmap(struct file *, struct vm_area_struct *);
-
/* name.c */
unsigned char hpfs_upcase(unsigned char *, unsigned char);
int hpfs_symlink(struct inode *, struct dentry *, const char *);
int hpfs_unlink(struct inode *, struct dentry *);
int hpfs_rmdir(struct inode *, struct dentry *);
-int hpfs_readlink(struct dentry *, char *, int);
-struct dentry *hpfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+int hpfs_symlink_readpage(struct dentry *, struct page *);
int hpfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/* super.c */
NULL, /* readdir - bad */
NULL, /* poll - default */
NULL, /* ioctl - default */
- generic_file_mmap/*hpfs_mmap*/, /* mmap */
+ generic_file_mmap, /* mmap */
hpfs_open, /* open */
NULL, /* flush */
hpfs_file_release, /* release */
const struct inode_operations hpfs_symlink_iops =
{
- NULL, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- hpfs_readlink, /* readlink */
- hpfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: hpfs_symlink_readpage
};
-
void hpfs_read_inode(struct inode *i)
{
struct buffer_head *bh;
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
}
-int hpfs_readlink(struct dentry *dentry, char *buf, int len)
+int hpfs_symlink_readpage(struct dentry *dentry, struct page *page)
{
+ char *link = (char*)kmap(page);
struct inode *i = dentry->d_inode;
struct fnode *fnode;
struct buffer_head *bh;
- char *symlink;
- int slen;
- if (!S_ISLNK(i->i_mode)) {
- return -EINVAL;
- }
- if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
- return -EIO;
- }
- if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
- brelse(bh);
- return -EFSERROR;
- }
- brelse(bh);
- if (slen > len) slen = len;
- memcpy_tofs(buf, symlink, slen);
- kfree(symlink);
- return slen;
-}
+ int err;
-struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
- unsigned int follow)
-{
- struct inode *inode = dinode->d_inode;
- char *link;
- unsigned len;
- struct buffer_head *bh;
- struct fnode *fnode;
- if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
- dput(dinode);
- return ERR_PTR(-EIO);
- }
- if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
- brelse(bh);
- dput(dinode);
- return ERR_PTR(-EIO);
- }
+ err = -EIO;
+ if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
+ goto fail;
+ err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
brelse(bh);
- UPDATE_ATIME(inode);
- ddir = lookup_dentry(link, ddir, follow);
- kfree(link);
- return ddir;
-}
+ if (err)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
+}
+
int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
#include "rock.h"
return 0;
}
+static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr)
+{
+ int slen;
+ int rootflag;
+ struct SL_component *oldslp;
+ struct SL_component *slp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ while (slen > 1) {
+ rootflag = 0;
+ switch (slp->flags & ~1) {
+ case 0:
+ memcpy(rpnt, slp->text, slp->len);
+ rpnt+=slp->len;
+ break;
+ case 4:
+ *rpnt++='.';
+ /* fallthru */
+ case 2:
+ *rpnt++='.';
+ break;
+ case 8:
+ rootflag = 1;
+ *rpnt++='/';
+ break;
+ default:
+ printk("Symlink component flag not implemented (%d)\n",
+ slp->flags);
+ }
+ slen -= slp->len + 2;
+ oldslp = slp;
+ slp = (struct SL_component *) ((char *) slp + slp->len + 2);
+
+ if (slen < 2) {
+ /*
+ * If there is another SL record, and this component
+ * record isn't continued, then add a slash.
+ */
+ if ((rr->u.SL.flags & 1) && !(oldslp->flags & 1))
+ *rpnt++='/';
+ break;
+ }
+
+ /*
+ * If this component record isn't continued, then append a '/'.
+ */
+ if (!rootflag && !(oldslp->flags & 1))
+ *rpnt++='/';
-/* Returns the name of the file that this inode is symlinked to. This is
- in malloc'd memory, so it needs to be freed, once we are through with it */
+ }
+ return rpnt;
+}
-char * get_rock_ridge_symlink(struct inode * inode)
-{
- unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
- unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
- struct buffer_head * bh;
- char * rpnt = NULL;
- unsigned char * pnt;
- struct iso_directory_record * raw_inode;
- CONTINUE_DECLS;
- int block;
- int sig;
- int rootflag;
- int len;
- unsigned char * chr;
- struct rock_ridge * rr;
-
- if (!inode->i_sb->u.isofs_sb.s_rock)
- panic("Cannot have symlink with high sierra variant of iso filesystem\n");
- block = inode->i_ino >> bufbits;
- bh = bread(inode->i_dev, block, bufsize);
- if (!bh)
- goto out_noread;
-
- pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
-
- raw_inode = ((struct iso_directory_record *) pnt);
-
- /*
- * If we go past the end of the buffer, there is some sort of error.
- */
- if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
- goto out_bad_span;
-
- /* Now test for possible Rock Ridge extensions which will override some of
- these numbers in the inode structure. */
-
- SETUP_ROCK_RIDGE(raw_inode, chr, len);
-
- repeat:
- while (len > 1){ /* There may be one byte for padding somewhere */
- rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
- sig = (chr[0] << 8) + chr[1];
- chr += rr->len;
- len -= rr->len;
-
- switch(sig){
- case SIG('R','R'):
- if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
- break;
- case SIG('S','P'):
- CHECK_SP(goto out);
- break;
- case SIG('S','L'):
- {int slen;
- struct SL_component * oldslp;
- struct SL_component * slp;
- slen = rr->len - 5;
- slp = &rr->u.SL.link;
- while (slen > 1){
- if (!rpnt){
- rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
- if (!rpnt) goto out;
- *rpnt = 0;
- };
- rootflag = 0;
- switch(slp->flags &~1){
- case 0:
- strncat(rpnt,slp->text, slp->len);
- break;
- case 2:
- strcat(rpnt,".");
- break;
- case 4:
- strcat(rpnt,"..");
- break;
- case 8:
- rootflag = 1;
- strcat(rpnt,"/");
- break;
- default:
- printk("Symlink component flag not implemented (%d)\n",slen);
- };
- slen -= slp->len + 2;
- oldslp = slp;
- slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
-
- if(slen < 2) {
- /*
- * If there is another SL record, and this component record
- * isn't continued, then add a slash.
- */
- if( ((rr->u.SL.flags & 1) != 0)
- && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
- break;
- }
+/* readpage() for symlinks: reads symlink contents into the page and either
+ makes it uptodate and returns 0 or returns error (-EIO) */
- /*
- * If this component record isn't continued, then append a '/'.
- */
- if( (!rootflag)
- && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
-
- };
- break;
- case SIG('C','E'):
- CHECK_CE; /* This tells is if there is a continuation record */
- break;
- default:
- break;
- }
- };
- };
- MAYBE_CONTINUE(repeat,inode);
-
-out_freebh:
+int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
+{
+ struct inode *inode = dentry->d_inode;
+ char *link = (char*)kmap(page);
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
+ struct buffer_head *bh;
+ char *rpnt = link;
+ unsigned char *pnt;
+ struct iso_directory_record *raw_inode;
+ CONTINUE_DECLS;
+ int block;
+ int sig;
+ int len;
+ unsigned char *chr;
+ struct rock_ridge *rr;
+
+ if (!inode->i_sb->u.isofs_sb.s_rock)
+ panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
+
+ block = inode->i_ino >> bufbits;
+ bh = bread(inode->i_dev, block, bufsize);
+ if (!bh)
+ goto out_noread;
+
+ pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
+
+ raw_inode = (struct iso_directory_record *) pnt;
+
+ /*
+ * If we go past the end of the buffer, there is some sort of error.
+ */
+ if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
+ goto out_bad_span;
+
+ /* Now test for possible Rock Ridge extensions which will override
+ some of these numbers in the inode structure. */
+
+ SETUP_ROCK_RIDGE(raw_inode, chr, len);
+
+ repeat:
+ while (len > 1) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0)
+ goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch (sig) {
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] & RR_SL) == 0)
+ goto out;
+ break;
+ case SIG('S', 'P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('S', 'L'):
+ rpnt = get_symlink_chunk(rpnt, rr);
+ break;
+ case SIG('C', 'E'):
+ /* This tells is if there is a continuation record */
+ CHECK_CE;
+ default:
+ break;
+ }
+ }
+ MAYBE_CONTINUE(repeat, inode);
+
+ if (rpnt == link)
+ goto fail;
brelse(bh);
- return rpnt;
+ *rpnt = '\0';
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
/* error exit from macro */
-out:
- if(buffer)
+ out:
+ if (buffer)
kfree(buffer);
- if(rpnt)
- kfree(rpnt);
- rpnt = NULL;
- goto out_freebh;
-out_noread:
+ goto fail;
+ out_noread:
printk("unable to read i-node block");
- goto out_freebh;
-out_bad_span:
+ goto fail;
+ out_bad_span:
printk("symlink spans iso9660 blocks\n");
- goto out_freebh;
+ fail:
+ brelse(bh);
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
#include <linux/stat.h>
#include <linux/malloc.h>
-#include <asm/uaccess.h>
-
-static int isofs_readlink(struct dentry *, char *, int);
-static struct dentry * isofs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
/*
* symlinks can't do much...
*/
struct inode_operations isofs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- isofs_readlink, /* readlink */
- isofs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: rock_ridge_symlink_readpage
};
-
-static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- char * pnt;
- int i;
-
- if (buflen > 1023)
- buflen = 1023;
- pnt = get_rock_ridge_symlink(dentry->d_inode);
-
- if (!pnt)
- return 0;
-
- i = strlen(pnt);
- if (i > buflen)
- i = buflen;
- if (copy_to_user(buffer, pnt, i))
- i = -EFAULT;
- kfree(pnt);
- return i;
-}
-
-static struct dentry * isofs_follow_link(struct dentry * dentry,
- struct dentry *base,
- unsigned int follow)
-{
- char * pnt;
-
- pnt = get_rock_ridge_symlink(dentry->d_inode);
- if(!pnt) {
- dput(base);
- return ERR_PTR(-ELOOP);
- }
-
- base = lookup_dentry(pnt, base, follow);
-
- kfree(pnt);
- return base;
-}
if ((follow & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
- if (current->link_count < 5) {
+ if (current->link_count < 32) {
struct dentry * result;
current->link_count++;
return len;
}
-struct dentry *
-vfs_follow_link(struct dentry *dentry, struct dentry *base,
-unsigned int follow, char *link)
+static inline struct dentry *
+__vfs_follow_link(struct dentry *dentry, struct dentry *base,
+ unsigned follow, char *link)
{
struct dentry *result;
UPDATE_ATIME(dentry->d_inode);
return (struct dentry *)link;
}
+struct dentry *
+vfs_follow_link(struct dentry *dentry, struct dentry *base,
+unsigned int follow, char *link)
+{
+ return __vfs_follow_link(dentry,base,follow,link);
+}
+
/* get the link contents into pagecache */
static char *page_getlink(struct dentry * dentry, struct page **ppage)
{
{
struct page *page = NULL;
char *s = page_getlink(dentry, &page);
- struct dentry *res = vfs_follow_link(dentry,base,follow,s);
+ struct dentry *res = __vfs_follow_link(dentry,base,follow,s);
if (page) {
kunmap(page);
page_cache_release(page);
#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
-static int ncp_readlink(struct dentry *, char *, int);
-static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
int ncp_create_new(struct inode *dir, struct dentry *dentry,
int mode,int attributes);
-/*
- * symlinks can't do much...
- */
-struct inode_operations ncp_symlink_inode_operations={
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ncp_readlink, /* readlink */
- ncp_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
-/* ----- follow a symbolic link ------------------------------------------ */
+/* ----- read a symbolic link ------------------------------------------ */
-static struct dentry *ncp_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
+static int ncp_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode=dentry->d_inode;
int error, length, len, cnt;
- char *link, *buf;
-
-#ifdef DEBUG
- PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
-#endif
-
- if(!S_ISLNK(inode->i_mode)) {
- dput(base);
- return ERR_PTR(-EINVAL);
- }
+ char *link;
+ char *buf = (char*)kmap(page);
- if(ncp_make_open(inode,O_RDONLY)) {
- dput(base);
- return ERR_PTR(-EIO);
- }
+ error = -EIO;
+ if (ncp_make_open(inode,O_RDONLY))
+ goto fail;
+ error = -ENOMEM;
for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
- if (cnt > 10) {
- dput(base);
- return ERR_PTR(-EAGAIN); /* -ENOMEM? */
- }
+ if (cnt > 10)
+ goto fail;
schedule();
}
error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length);
- if (error!=0 || length<NCP_MIN_SYMLINK_SIZE ||
- ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
- dput(base);
+ if (error) {
kfree(link);
- return ERR_PTR(-EIO);
+ goto fail;
}
-
- len = NCP_MAX_SYMLINK_SIZE;
- buf = (char *) kmalloc(len, GFP_NFS);
- if (!buf) {
- dput(base);
+ if (length<NCP_MIN_SYMLINK_SIZE ||
+ ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||
+ ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+ error = -EIO;
kfree(link);
- return ERR_PTR(-EAGAIN);
- }
- error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
- kfree(link);
- if (error) {
- dput(base);
- kfree(buf);
- return ERR_PTR(error);
- }
-
- /* UPDATE_ATIME(inode); */
- base = lookup_dentry(buf, base, follow);
- kfree(buf);
-
- return base;
-}
-
-/* ----- read symbolic link ---------------------------------------------- */
-
-static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode=dentry->d_inode;
- char *link, *buf;
- int length, len, error;
-
-#ifdef DEBUG
- PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
-#endif
-
- if(!S_ISLNK(inode->i_mode))
- return -EINVAL;
-
- if(ncp_make_open(inode,O_RDONLY))
- return -EIO;
-
- if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE,GFP_NFS))==NULL)
- return -ENOMEM;
-
- error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
- 0,NCP_MAX_SYMLINK_SIZE,link,&length);
-
- if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
- ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
- error = -EIO;
- goto out;
+ goto fail;
}
len = NCP_MAX_SYMLINK_SIZE;
- buf = (char *) kmalloc(len, GFP_NFS);
- if (!buf) {
- error = -ENOMEM;
- goto out;
- }
error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
- if (error || buflen < len) {
- error = -EIO;
- kfree(buf);
- goto out;
- }
-
- error = len;
- if(copy_to_user(buffer, buf, error))
- error = -EFAULT;
- kfree(buf);
-
-out:
kfree(link);
+ if (error)
+ goto fail;
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
return error;
}
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations ncp_symlink_inode_operations={
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: ncp_symlink_readpage,
+};
+
/* ----- create a new symbolic link -------------------------------------- */
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
* inspired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
+ *
+ * Wow. It looks like we could support them on FAT with little (if any)
+ * problems. Oh, well...
*/
-#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/umsdos_fs.h>
-#include <linux/malloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static struct file_operations umsdos_symlink_operations;
-
-
-/*
- * Read the data associate with the symlink.
- * Return length read in buffer or a negative error code.
- *
- */
-
-int umsdos_readlink_x ( struct dentry *dentry,
- char *buffer,
- int bufsiz)
-{
- size_t size = dentry->d_inode->i_size;
- loff_t loffs = 0;
- ssize_t ret;
- struct file filp;
-
-Printk((KERN_DEBUG "UMSDOS_read: %s/%s, size=%u\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, size));
-
- fill_new_filp (&filp, dentry);
- filp.f_reada = 0;
- filp.f_flags = O_RDONLY;
- filp.f_op = &umsdos_symlink_operations;
-
- if (size > bufsiz)
- size = bufsiz;
-
- ret = fat_file_read (&filp, buffer, size, &loffs);
- if (ret != size) {
- ret = -EIO;
- }
- return ret;
-}
-
-
-
-static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
-{
- return umsdos_readlink_x (dentry, buffer, buflen);
-}
-
-/* this one mostly stolen from romfs :) */
-static struct dentry *UMSDOS_followlink (struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- char *symname;
- int len, cnt;
- mm_segment_t old_fs = get_fs ();
-
-Printk((KERN_DEBUG "UMSDOS_followlink /mn/: (%s/%s)\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
-
- len = inode->i_size;
-
- if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
- dentry = ERR_PTR (-ENOMEM);
- goto outnobuf;
- }
-
- set_fs (KERNEL_DS); /* we read into kernel space this time */
- cnt = umsdos_readlink_x (dentry, symname, len);
- set_fs (old_fs);
-
- if (len != cnt) {
- dentry = ERR_PTR (-EIO);
- goto out;
- }
-
- symname[len] = 0;
- dentry = lookup_dentry (symname, base, follow);
- kfree (symname);
-
- if (0) {
- out:
- kfree (symname);
- outnobuf:
- dput (base);
- }
- return dentry;
-}
-
-/* needed to patch the file structure */
-static struct file_operations umsdos_symlink_operations =
-{
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* no flush code */
- NULL, /* release */
- NULL /* fsync */
-};
-
struct inode_operations umsdos_symlink_inode_operations =
{
- NULL, /* default file operations (none) */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- UMSDOS_readlink, /* readlink */
- UMSDOS_followlink, /* followlink */
- fat_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: fat_get_block,
+ readpage: block_read_full_page
};
-
#if SPINLOCK_DEBUG
if (lock->magic != SPINLOCK_MAGIC)
BUG();
+ if (!lock->lock)
+ BUG();
#endif
__asm__ __volatile__(
spin_unlock_string
#define _LINUX_CDROM_H
#include <linux/types.h>
+#include <asm/byteorder.h>
/*******************************************************
* As of Linux 2.1.x, all Linux CD-ROM application programs will use this
/* for CDROM_PACKET_COMMAND ioctl */
struct cdrom_generic_command
{
- unsigned char cmd[CDROM_PACKET_SIZE];
- unsigned char *buffer;
- unsigned int buflen;
- int stat;
- void *reserved[4];
+ unsigned char cmd[CDROM_PACKET_SIZE];
+ unsigned char *buffer;
+ unsigned int buflen;
+ int stat;
+ struct request_sense *sense;
+ void *reserved[3];
};
};
struct dvd_host_send_rpcstate {
+ __u8 type;
__u8 pdrc;
};
struct dvd_lu_send_rpcstate lrpcs;
} dvd_authinfo;
+struct request_sense {
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 valid : 1;
+ __u8 error_code : 7;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 error_code : 7;
+ __u8 valid : 1;
+#endif
+ __u8 segment_number;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ __u8 reserved1 : 2;
+ __u8 ili : 1;
+ __u8 reserved2 : 1;
+ __u8 sense_key : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ __u8 sense_key : 4;
+ __u8 reserved2 : 1;
+ __u8 ili : 1;
+ __u8 reserved1 : 2;
+#endif
+ __u8 information[4];
+ __u8 add_sense_len;
+ __u8 command_info[4];
+ __u8 asc;
+ __u8 ascq;
+ __u8 fruc;
+ __u8 sks[3];
+ __u8 asb[46];
+};
+
#ifdef __KERNEL__
struct cdrom_write_settings {
#define READ 0
#define WRITE 1
#define READA 2 /* read-ahead - don't block if no resources */
+#define SPECIAL 4 /* For non-blockdevice requests in request queue */
#define WRITERAW 5 /* raw write - don't play with buffer lists */
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
-extern char * get_rock_ridge_symlink(struct inode *);
+extern int rock_ridge_symlink_readpage(struct dentry *, struct page *);
extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *);
int get_joliet_filename(struct iso_directory_record *, struct inode *, unsigned char *);
mmlist_modify_unlock();
return mm;
}
- mmlist_modify_unlock();
kmem_cache_free(mm_cachep, mm);
}
return NULL;