Commit 5bdbe23a authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.25pre3

parent a3b4d222
......@@ -903,6 +903,8 @@ S: Maintained
UDF FILESYSTEM
P: Ben Fennema
M: bfennema@falcon.csc.calpoly.edu
P: Dave Boynton
M: dave@trylinux.com
L: linux_udf@hootie.lvld.hp.com
W: http://www.trylinux.com/projects/udf/index.html
S: Maintained
......
/*
* cycx_drv.c cycx Support Module.
* cycx_drv.c Cyclom 2X Support Module.
*
* This module is a library of common hardware-specific
* functions used by all Cyclades sync and some async (8x & 16x)
* drivers.
* functions used by the Cyclades Cyclom 2X sync card.
*
* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
......@@ -16,6 +15,11 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
* 1999/10/26 acme use isa_read[bw], isa_write[bw] and isa_memcpy_to
* and fromio
* 1999/10/23 acme cleanup to only supports cyclom2x: all the other
* boards are no longer manufactured by cyclades, if
* someone wants to support them... be my guest!
* 1999/05/28 acme cycx_intack & cycx_intde gone for good
* 1999/05/18 acme lots of unlogged work, submitting to Linus...
* 1999/01/03 acme more judicious use of data types
......@@ -27,16 +31,16 @@
* to ack an int in cycx_drv.c, only handle it in
* cyx_isr (or in the other protocols: cyp_isr,
* cyf_isr, when they get implemented.
* Dec 31, 1998 Arnaldo cycx_data_boot & cycx_code_boot fixed, crossing
* Dec 31, 1998 acme cycx_data_boot & cycx_code_boot fixed, crossing
* fingers to see x25_configure in cycx_x25.c
* work... :)
* Dec 26, 1998 Arnaldo load implementation fixed, seems to work! :)
* Dec 26, 1998 acme load implementation fixed, seems to work! :)
* cycx_2x_dpmbase_options with all the possible
* DPM addresses (20).
* cycx_intr implemented (test this!)
* general code cleanup
* Dec 8, 1998 Ivan Passos Cyclom-2X firmware load implementation.
* Aug 8, 1998 Arnaldo Initial version.
* Aug 8, 1998 acme Initial version.
*/
#ifdef MODULE
......@@ -57,11 +61,11 @@
#include <asm/io.h> /* for inb(), outb(), etc. */
#define MOD_VERSION 0
#define MOD_RELEASE 2
#define MOD_RELEASE 3
#ifdef MODULE
MODULE_AUTHOR("Arnaldo Carvalho de Melo");
MODULE_DESCRIPTION("Cyclades Sync Cards Driver.");
MODULE_DESCRIPTION("Cyclom 2x Sync Card Driver");
#endif
/* Function Prototypes */
......@@ -70,15 +74,12 @@ int init_module (void);
void cleanup_module (void);
/* Hardware-specific functions */
static int cycx_detect (cycxhw_t *hw);
static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len);
static int cycx_init (cycxhw_t *hw);
static int cycx_reset (cycxhw_t *hw);
static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len);
static void cycx_bootcfg (cycxhw_t *hw);
static int init_cycx_2x (cycxhw_t *hw);
static int reset_cycx_2x (u32 addr);
static int detect_cycx_2x (u32 addr);
static int init_cyc2x (cycxhw_t *hw);
static int reset_cyc2x (u32 addr);
static int detect_cyc2x (u32 addr);
/* Miscellaneous functions */
static void delay_cycx (int sec);
......@@ -87,19 +88,25 @@ static u16 checksum (u8 *buf, u32 len);
#define wait_cyc(addr) cycx_exec(addr + CMD_OFFSET)
/* Global Data
* Note: All data must be explicitly initialized!!! */
#define cyc2x_readb(b) isa_readb(b)
#define cyc2x_readw(b) isa_readw(b)
#define cyc2x_writeb(b, addr) isa_writeb(b, addr)
#define cyc2x_writew(w, addr) isa_writew(w, addr)
#define cyc2x_memcpy_toio(addr, buf, len) isa_memcpy_toio((addr), buf, len)
#define cyc2x_memcpy_fromio(buf, addr, len) isa_memcpy_fromio(buf, (addr), len)
/* Global Data */
/* private data */
static char modname[] = "cycx_drv";
static char fullname[] = "Cyclom X Support Module";
static char fullname[] = "Cyclom 2X Support Module";
static char copyright[] = "(c) 1998, 1999 Arnaldo Carvalho de Melo";
/* Hardware configuration options.
* These are arrays of configuration options used by verification routines.
* The first element of each array is its size (i.e. number of options).
*/
static u32 cycx_2x_dpmbase_options[] =
static u32 cyc2x_dpmbase_options[] =
{
20,
0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000, 0xB8000,
......@@ -143,32 +150,18 @@ void cleanup_module (void)
EXPORT_SYMBOL(cycx_setup);
int cycx_setup (cycxhw_t *hw, void *cfm, u32 len)
{
u32 *irq_opt = NULL; /* IRQ options */
u32 *dpmbase_opt = NULL;/* DPM window base options */
int err = 0;
if (cycx_detect(hw)) {
printk(KERN_ERR "%s: adapter Cyclom %uX not found at "
if (!detect_cyc2x(hw->dpmbase)) {
printk(KERN_ERR "%s: adapter Cyclom 2X not found at "
"address 0x%lX!\n",
modname, hw->type, (unsigned long) hw->dpmbase);
modname, (unsigned long) hw->dpmbase);
return -EINVAL;
}
printk(KERN_INFO "%s: found Cyclom %uX card at address 0x%lx.\n",
modname, hw->type, (unsigned long) hw->dpmbase);
switch (hw->type) {
case CYCX_2X:
irq_opt = cycx_2x_irq_options;
dpmbase_opt = cycx_2x_dpmbase_options;
break;
default:
printk(KERN_ERR "%s: unknown card.\n", modname);
return -EINVAL;
}
printk(KERN_INFO "%s: found Cyclom 2X card at address 0x%lx.\n",
modname, (unsigned long) hw->dpmbase);
/* Verify IRQ configuration options */
if (!get_option_index(irq_opt, hw->irq)) {
if (!get_option_index(cycx_2x_irq_options, hw->irq)) {
printk (KERN_ERR "%s: IRQ %d is illegal!\n", modname, hw->irq);
return -EINVAL;
}
......@@ -179,60 +172,35 @@ int cycx_setup (cycxhw_t *hw, void *cfm, u32 len)
modname);
return -EINVAL;
}
else if (!get_option_index(dpmbase_opt, hw->dpmbase)) {
else if (!get_option_index(cyc2x_dpmbase_options, hw->dpmbase)) {
printk(KERN_ERR "%s: memory address 0x%lX is illegal!\n",
modname, (unsigned long) hw->dpmbase);
return -EINVAL;
}
hw->dpmsize = CYCX_WINDOWSIZE;
/* FIXME! Is this the only amount ever available? */
hw->memory = 0x40000;
cycx_init(hw);
init_cyc2x(hw);
printk(KERN_INFO "%s: dual-port memory window is set at 0x%lX.\n",
modname, (unsigned long) hw->dpmbase);
printk(KERN_INFO "%s: found %luK bytes of on-board memory.\n",
modname, (unsigned long) hw->memory / 1024);
/* Load firmware. If loader fails then shut down adapter */
err = cycx_load(hw, cfm, len);
if (err) cycx_down(hw); /* shutdown adapter */
return err;
}
/* Shut down CYCX: disable shared memory access and interrupts, stop CPU,etc.*/
EXPORT_SYMBOL(cycx_down);
int cycx_down (cycxhw_t *hw)
{
return 0; /* FIXME: anything needed here? */
return load_cyc2x(hw, cfm, len);
}
/* Enable interrupt generation. */
EXPORT_SYMBOL(cycx_inten);
int cycx_inten (cycxhw_t *hw)
void cycx_inten (cycxhw_t *hw)
{
switch (hw->type) {
case CYCX_2X: writeb (0, hw->dpmbase); break;
default: return -EINVAL;
}
return 0;
cyc2x_writeb (0, hw->dpmbase);
}
/* Generate an interrupt to adapter's CPU. */
EXPORT_SYMBOL(cycx_intr);
int cycx_intr (cycxhw_t *hw)
void cycx_intr (cycxhw_t *hw)
{
switch (hw->type) {
case CYCX_2X:
writew(0, hw->dpmbase + GEN_CYCX_INTR);
return 0;
default: return -EINVAL;
}
return 0;
cyc2x_writew(0, hw->dpmbase + GEN_CYCX_INTR);
}
/* Execute Adapter Command.
......@@ -244,7 +212,7 @@ int cycx_exec (u32 addr)
u16 i = 0;
/* wait till addr content is zeroed */
while (readw(addr) != 0) {
while (cyc2x_readw(addr)) {
udelay(1000);
if (++i > 50) return -1;
}
......@@ -257,8 +225,8 @@ int cycx_exec (u32 addr)
EXPORT_SYMBOL(cycx_peek);
int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len)
{
if (len == 1) *(u8*)buf = readb (hw->dpmbase + addr);
else memcpy_fromio(buf, hw->dpmbase + addr, len);
if (len == 1) *(u8*)buf = cyc2x_readb (hw->dpmbase + addr);
else cyc2x_memcpy_fromio(buf, hw->dpmbase + addr, len);
return 0;
}
......@@ -268,38 +236,13 @@ int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len)
EXPORT_SYMBOL(cycx_poke);
int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len)
{
if (len == 1) writeb (*(u8*)buf, hw->dpmbase + addr);
else memcpy_toio(hw->dpmbase + addr, buf, len);
if (len == 1) cyc2x_writeb (*(u8*)buf, hw->dpmbase + addr);
else cyc2x_memcpy_toio(hw->dpmbase + addr, buf, len);
return 0;
}
/* Hardware-Specific Functions */
/* Detect adapter type.
* o if adapter type is specified then call detection routine for that adapter
* type. Otherwise call detection routines for every adapter types until
* adapter is detected.
*
* Notes:
* 1) Detection tests are destructive! Adapter will be left in shutdown state
* after the test. */
static int cycx_detect (cycxhw_t *hw)
{
int err = 0;
if (!hw->dpmbase) return -EFAULT;
switch (hw->type) {
case CYCX_2X:
if (!detect_cycx_2x(hw->dpmbase)) err = -ENODEV;
break;
default:
if (detect_cycx_2x(hw->dpmbase)) hw->type = CYCX_2X;
else err = -ENODEV;
}
return err;
}
/* Load Aux Routines */
/* Reset board hardware.
......@@ -309,10 +252,10 @@ static int memory_exists(u32 addr)
int timeout = 0;
for (; timeout < 3 ; timeout++) {
writew (TEST_PATTERN, addr + 0x10);
cyc2x_writew (TEST_PATTERN, addr + 0x10);
if (readw (addr + 0x10) == TEST_PATTERN)
if (readw (addr + 0x10) == TEST_PATTERN) return 1;
if (cyc2x_readw (addr + 0x10) == TEST_PATTERN)
if (cyc2x_readw (addr + 0x10) == TEST_PATTERN) return 1;
delay_cycx(1);
}
......@@ -320,17 +263,6 @@ static int memory_exists(u32 addr)
return 0;
}
/* Reset board hardware. */
static int cycx_reset(cycxhw_t *hw)
{
/* Reset board */
switch (hw->type) {
case CYCX_2X: return reset_cycx_2x(hw->dpmbase);
}
return -EINVAL;
}
/* Load reset code. */
static void reset_load(u32 addr, u8 *buffer, u32 cnt)
{
......@@ -339,7 +271,7 @@ static void reset_load(u32 addr, u8 *buffer, u32 cnt)
for ( i = 0 ; i < cnt ; i++) {
for (j = 0 ; j < 50 ; j++); /* Delay - FIXME busy waiting... */
writeb(*buffer++, pt_code++);
cyc2x_writeb(*buffer++, pt_code++);
}
}
......@@ -348,8 +280,8 @@ static void reset_load(u32 addr, u8 *buffer, u32 cnt)
* o wait for reset code to copy it to right portion of memory */
static int buffer_load(u32 addr, u8 *buffer, u32 cnt)
{
memcpy_toio(addr + DATA_OFFSET, buffer, cnt);
writew(GEN_BOOT_DAT, addr + CMD_OFFSET);
cyc2x_memcpy_toio(addr + DATA_OFFSET, buffer, cnt);
cyc2x_writew(GEN_BOOT_DAT, addr + CMD_OFFSET);
return wait_cyc(addr);
}
......@@ -357,14 +289,14 @@ static int buffer_load(u32 addr, u8 *buffer, u32 cnt)
static void cycx_start (u32 addr)
{
/* put in 0x30 offset the jump instruction to the code entry point */
writeb(0xea, addr + 0x30);
writeb(0x00, addr + 0x31);
writeb(0xc4, addr + 0x32);
writeb(0x00, addr + 0x33);
writeb(0x00, addr + 0x34);
cyc2x_writeb(0xea, addr + 0x30);
cyc2x_writeb(0x00, addr + 0x31);
cyc2x_writeb(0xc4, addr + 0x32);
cyc2x_writeb(0x00, addr + 0x33);
cyc2x_writeb(0x00, addr + 0x34);
/* cmd to start executing code */
writew(GEN_START, addr + CMD_OFFSET);
cyc2x_writew(GEN_START, addr + CMD_OFFSET);
}
/* Load and boot reset code. */
......@@ -372,15 +304,15 @@ static void cycx_reset_boot(u32 addr, u8 *code, u32 len)
{
u32 pt_start = addr + START_OFFSET;
writeb(0xea, pt_start++); /* jmp to f000:3f00 */
writeb(0x00, pt_start++);
writeb(0xfc, pt_start++);
writeb(0x00, pt_start++);
writeb(0xf0, pt_start);
cyc2x_writeb(0xea, pt_start++); /* jmp to f000:3f00 */
cyc2x_writeb(0x00, pt_start++);
cyc2x_writeb(0xfc, pt_start++);
cyc2x_writeb(0x00, pt_start++);
cyc2x_writeb(0xf0, pt_start);
reset_load(addr, code, len);
/* 80186 was in hold, go */
writeb(0, addr + START_CPU);
cyc2x_writeb(0, addr + START_CPU);
delay_cycx(1);
}
......@@ -391,14 +323,14 @@ static int cycx_data_boot(u32 addr, u8 *code, u32 len)
u32 i;
/* boot buffer lenght */
writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
writew(GEN_DEFPAR, pt_boot_cmd);
cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
cyc2x_writew(GEN_DEFPAR, pt_boot_cmd);
if (wait_cyc(addr) < 0) return 2;
writew(0, pt_boot_cmd + sizeof(u16));
writew(0x4000, pt_boot_cmd + 2 * sizeof(u16));
writew(GEN_SET_SEG, pt_boot_cmd);
cyc2x_writew(0, pt_boot_cmd + sizeof(u16));
cyc2x_writew(0x4000, pt_boot_cmd + 2 * sizeof(u16));
cyc2x_writew(GEN_SET_SEG, pt_boot_cmd);
if (wait_cyc(addr) < 0) return 2;
......@@ -420,14 +352,14 @@ static int cycx_code_boot(u32 addr, u8 *code, u32 len)
u32 i;
/* boot buffer lenght */
writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
writew(GEN_DEFPAR, pt_boot_cmd);
cyc2x_writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
cyc2x_writew(GEN_DEFPAR, pt_boot_cmd);
if (wait_cyc(addr) == -1) return 2;
writew(0x0000, pt_boot_cmd + sizeof(u16));
writew(0xc400, pt_boot_cmd + 2 * sizeof(u16));
writew(GEN_SET_SEG, pt_boot_cmd);
cyc2x_writew(0x0000, pt_boot_cmd + sizeof(u16));
cyc2x_writew(0xc400, pt_boot_cmd + 2 * sizeof(u16));
cyc2x_writew(GEN_SET_SEG, pt_boot_cmd);
if (wait_cyc(addr) == -1) return 1;
......@@ -440,22 +372,12 @@ static int cycx_code_boot(u32 addr, u8 *code, u32 len)
return 0;
}
/* Initialize CYCX hardware: setup memory window, IRQ, etc. */
static int cycx_init (cycxhw_t *hw)
{
switch (hw->type) {
case CYCX_2X: return init_cycx_2x(hw);
}
return -EINVAL;
}
/* Load adapter from the memory image of the CYCX firmware module.
* o verify firmware integrity and compatibility
* o start adapter up */
static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
static int load_cyc2x (cycxhw_t *hw, cfm_t *cfm, u32 len)
{
int i, j, status;
int i, j;
cycx_header_t *img_hdr;
u8 *reset_image,
*data_image,
......@@ -469,7 +391,7 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
/* Verify firmware signature */
if (strcmp(cfm->signature, CFM_SIGNATURE)) {
printk(KERN_ERR "%s:cycx_load: not Cyclom-2X firmware!\n",
printk(KERN_ERR "%s:load_cyc2x: not Cyclom-2X firmware!\n",
modname);
return -EINVAL;
}
......@@ -478,7 +400,7 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
/* Verify firmware module format version */
if (cfm->version != CFM_VERSION) {
printk(KERN_ERR "%s:cycx_load: firmware format %u rejected! "
printk(KERN_ERR "%s:" __FUNCTION__ ": firmware format %u rejected! "
"Expecting %u.\n",
modname, cfm->version, CFM_VERSION);
return -EINVAL;
......@@ -492,7 +414,7 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
if (((len - sizeof(cfm_t) - 1) != cfm->info.codesize) ||
*/
if (cksum != cfm->checksum) {
printk(KERN_ERR "%s:cycx_load: firmware corrupted!\n", modname);
printk(KERN_ERR "%s:" __FUNCTION__ ": firmware corrupted!\n", modname);
printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
len - sizeof(cfm_t) - 1, cfm->info.codesize);
printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
......@@ -504,7 +426,7 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
img_hdr = (cycx_header_t*)(((u8*) cfm) + sizeof(cfm_t) - 1);
#ifdef FIRMWARE_DEBUG
printk(KERN_INFO "%s:cycx_load: image sizes\n", modname);
printk(KERN_INFO "%s:" __FUNCTION__ ": image sizes\n", modname);
printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
printk(KERN_INFO " data=%lu\n", img_hdr->data_size);
printk(KERN_INFO " code=%lu\n", img_hdr->code_size);
......@@ -521,20 +443,20 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
for (i = 0 ; i < 5 ; i++) {
/* Reset Cyclom hardware */
if ((status = cycx_reset(hw)) != 0) {
if (!reset_cyc2x(hw->dpmbase)) {
printk(KERN_ERR "%s: dpm problem or board not "
"found (%d).\n", modname, status);
"found.\n", modname);
return -EINVAL;
}
/* Load reset.bin */
cycx_reset_boot(hw->dpmbase, reset_image, img_hdr->reset_size);
/* reset is waiting for boot */
writew(GEN_POWER_ON, pt_cycld);
cyc2x_writew(GEN_POWER_ON, pt_cycld);
delay_cycx(1);
for (j = 0 ; j < 3 ; j++)
if (!readw(pt_cycld)) goto reset_loaded;
if (!cyc2x_readw(pt_cycld)) goto reset_loaded;
else delay_cycx(1);
}
......@@ -542,18 +464,16 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
return -EINVAL;
reset_loaded:
/* Load data.bin */
if((status = cycx_data_boot(hw->dpmbase, data_image,
img_hdr->data_size)) != 0) {
printk(KERN_ERR "%s: cannot load data file (%d).\n",
modname, status);
if(cycx_data_boot(hw->dpmbase, data_image,
img_hdr->data_size)) {
printk(KERN_ERR "%s: cannot load data file.\n", modname);
return -EINVAL;
}
/* Load code.bin */
if((status = cycx_code_boot(hw->dpmbase, code_image,
img_hdr->code_size)) != 0) {
printk(KERN_ERR "%s: cannot load code file (%d).\n",
modname, status);
if(cycx_code_boot(hw->dpmbase, code_image,
img_hdr->code_size)) {
printk(KERN_ERR "%s: cannot load code file.\n", modname);
return -EINVAL;
}
......@@ -569,10 +489,7 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
printk(KERN_INFO "%s: firmware loaded!\n", modname);
/* enable interrupts */
if (cycx_inten(hw)) {
printk(KERN_ERR "%s: adapter hardware failure!\n", modname);
return -EIO;
}
cycx_inten(hw);
return 0;
}
......@@ -586,13 +503,15 @@ static int cycx_load (cycxhw_t *hw, cfm_t *cfm, u32 len)
static void cycx_bootcfg (cycxhw_t *hw)
{
/* use fixed buffers */
writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET);
cyc2x_writeb(FIXED_BUFFERS, hw->dpmbase + CONF_OFFSET);
}
/* Initialize CYCX_2X adapter. */
static int init_cycx_2x (cycxhw_t *hw)
static int init_cyc2x (cycxhw_t *hw)
{
if (!detect_cycx_2x(hw->dpmbase)) return -ENODEV;
if (!detect_cyc2x(hw->dpmbase))
return -ENODEV;
return 0;
}
......@@ -602,12 +521,12 @@ static int init_cycx_2x (cycxhw_t *hw)
* Return 1 if detected o.k. or 0 if failed.
* Note: This test is destructive! Adapter will be left in shutdown
* state after the test. */
static int detect_cycx_2x (u32 addr)
static int detect_cyc2x (u32 addr)
{
printk(KERN_INFO "%s: looking for a cyclom 2x at 0x%lX...\n",
modname, (unsigned long) addr);
reset_cycx_2x(addr);
reset_cyc2x(addr);
return memory_exists(addr);
}
......@@ -622,11 +541,11 @@ static int get_option_index (u32 *optlist, u32 optval)
}
/* Reset adapter's CPU. */
static int reset_cycx_2x (u32 addr)
static int reset_cyc2x (u32 addr)
{
writeb (0, addr + RST_ENABLE); delay_cycx (2);
writeb (0, addr + RST_DISABLE); delay_cycx (2);
return memory_exists(addr) ? 0 : 1;
cyc2x_writeb (0, addr + RST_ENABLE); delay_cycx (2);
cyc2x_writeb (0, addr + RST_DISABLE); delay_cycx (2);
return memory_exists(addr);
}
/* Delay */
......
/*
* cycx_main.c Cyclades Cyclom X Multiprotocol WAN Link Driver. Main module.
* cycx_main.c Cyclades Cyclom 2X WAN Link Driver. Main module.
*
* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
......@@ -40,7 +40,7 @@
#ifdef MODULE
MODULE_AUTHOR("Arnaldo Carvalho de Melo");
MODULE_DESCRIPTION("Cyclades Sync Cards Driver.");
MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
#endif
/* Defines & Macros */
......@@ -73,7 +73,7 @@ static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs);
/* private data */
static char drvname[] = "cyclomx";
static char fullname[] = "CYCLOM X(tm) Multiprotocol Driver";
static char fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
static char copyright[] = "(c) 1998, 1999 Arnaldo Carvalho de Melo";
static int ncards = CONFIG_CYCLOMX_CARDS;
static cycx_t *card_array = NULL; /* adapter data space */
......@@ -214,7 +214,6 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
card->hw.dpmbase = conf->maddr;
card->hw.dpmsize = CYCX_WINDOWSIZE;
card->hw.type = conf->hw_opt[0];
card->hw.fwid = CFID_X25_2X;
card->lock = SPIN_LOCK_UNLOCKED;
#if LINUX_VERSION_CODE >= 0x020300
......@@ -234,9 +233,7 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
wandev->dma = wandev->ioport = 0;
wandev->maddr = (unsigned long*)card->hw.dpmbase;
wandev->msize = card->hw.dpmsize;
wandev->hw_opt[0] = card->hw.type;
wandev->hw_opt[1] = card->hw.pclk;
wandev->hw_opt[2] = card->hw.memory;
wandev->hw_opt[2] = 0;
wandev->hw_opt[3] = card->hw.fwid;
/* Protocol-specific initialization */
......@@ -251,7 +248,6 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
}
if (err) {
cycx_down(&card->hw);
free_irq(irq, card);
return err;
}
......@@ -278,7 +274,6 @@ static int shutdown (wan_device_t *wandev)
card = wandev->private;
wandev->state = WAN_UNCONFIGURED;
cycx_down(&card->hw);
printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,wandev->irq);
free_irq(wandev->irq, card);
return 0;
......
/*
* cycx_x25.c CYCLOM X Multiprotocol WAN Link Driver. X.25 module.
* cycx_x25.c CYCLOM X WAN Link Driver. X.25 module.
*
* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
......@@ -11,6 +11,13 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
* 1999/10/27 acme use ARPHRD_HWX25 so that the x25 stack know
* that we have a X.25 stack implemented in
* firmware onboard
* 1999/10/18 acme support for X.25 sockets in if_send,
* beware: socket(AF_X25...) IS WORK IN PROGRESS,
* TCP/IP over X.25 via wanrouter not affected,
* working.
* 1999/10/09 acme chan_disc renamed to chan_disconnect,
* began adding support for X.25 sockets:
* conf->protocol in new_if
......@@ -52,14 +59,14 @@
* memset is put into the unresolved symbols
* instead of using the inline memset functions...
* 1999/01/02 acme began chan_connect, chan_send, x25_send
* Dec 31, 1998 Arnaldo x25_configure
* 1998/12/31 acme x25_configure
* this code can be compiled as non module
* Dec 27, 1998 Arnaldo code cleanup
* 1998/12/27 acme code cleanup
* IPX code wiped out! let's decrease code
* complexity for now, remember: I'm learning! :)
* bps_to_speed_code OK
* Dec 26, 1998 Arnaldo Minimal debug code cleanup
* Aug 08, 1998 Arnaldo Initial version.
* 1998/12/26 acme Minimal debug code cleanup
* 1998/08/08 acme Initial version.
*/
#define CYCLOMX_X25_DEBUG 1
......@@ -71,7 +78,7 @@
#include <linux/malloc.h> /* kmalloc(), kfree() */
#include <linux/wanrouter.h> /* WAN router definitions */
#include <asm/byteorder.h> /* htons(), etc. */
#include <linux/if_arp.h> /* ARPHRD_X25 */
#include <linux/if_arp.h> /* ARPHRD_HWX25 */
#include <linux/cyclomx.h> /* CYCLOM X common user API definitions */
#include <linux/cycx_x25.h> /* X.25 firmware API definitions */
......@@ -137,10 +144,11 @@ static int x25_configure (cycx_t *card, TX25Config *conf),
x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
/* channel functions */
int chan_connect (struct net_device *dev),
static int chan_connect (struct net_device *dev),
chan_send (struct net_device *dev, struct sk_buff *skb);
static void chan_disconnect (struct net_device *dev);
static void chan_disconnect (struct net_device *dev),
chan_x25_send_event(struct net_device *dev, u8 event);
/* Miscellaneous functions */
static void set_chan_state (struct net_device *dev, u8 state),
......@@ -288,11 +296,11 @@ int cyx_init (cycx_t *card, wandev_conf_t *conf)
card->wandev.interface = conf->interface;
card->wandev.clocking = conf->clocking;
card->wandev.station = conf->station;
card->isr = &cyx_isr;
card->isr = cyx_isr;
card->exec = NULL;
card->wandev.update = &update;
card->wandev.new_if = &new_if;
card->wandev.del_if = &del_if;
card->wandev.update = update;
card->wandev.new_if = new_if;
card->wandev.del_if = del_if;
card->wandev.state = WAN_DISCONNECTED;
return 0;
}
......@@ -328,7 +336,7 @@ static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *c
x25_channel_t *chan;
int err = 0;
if (conf->name[0] == '\0' || strlen(conf->name) > WAN_IFNAME_SZ) {
if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
printk(KERN_INFO "%s: invalid interface name!\n",card->devname);
return -EINVAL;
}
......@@ -403,7 +411,7 @@ static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *c
/* prepare network device data space for registration */
dev->name = chan->name;
dev->init = &if_init;
dev->init = if_init;
dev->priv = chan;
return 0;
}
......@@ -411,11 +419,6 @@ static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *c
/* Delete logical channel. */
static int del_if (wan_device_t *wandev, struct net_device *dev)
{
if (!dev) {
printk(KERN_ERR "cycx_x25:del_if:dev == NULL!\n");
return 0;
}
if (dev->priv) {
x25_channel_t *chan = dev->priv;
......@@ -447,16 +450,16 @@ static int if_init (struct net_device *dev)
wan_device_t *wandev = &card->wandev;
/* Initialize device driver entry points */
dev->open = &if_open;
dev->stop = &if_close;
dev->hard_header = &if_header;
dev->rebuild_header = &if_rebuild_hdr;
dev->hard_start_xmit = &if_send;
dev->get_stats = &if_stats;
dev->open = if_open;
dev->stop = if_close;
dev->hard_header = if_header;
dev->rebuild_header = if_rebuild_hdr;
dev->hard_start_xmit = if_send;
dev->get_stats = if_stats;
/* Initialize media-specific parameters */
dev->mtu = X25_CHAN_MTU;
dev->type = ARPHRD_X25; /* ARP h/w type */
dev->type = ARPHRD_HWX25; /* ARP h/w type */
dev->hard_header_len = 0; /* media header length */
dev->addr_len = 0; /* hardware address length */
......@@ -577,7 +580,8 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
"%s: unsupported Ethertype 0x%04X on interface %s!\n",
card->devname, skb->protocol, dev->name);
++chan->ifstats.tx_errors;
} else switch (chan->state) {
} else if (chan->protocol == ETH_P_IP) {
switch (chan->state) {
case WAN_DISCONNECTED:
if (chan_connect(dev)) {
dev->tbusy = 1;
......@@ -589,15 +593,44 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev->tbusy = 1;
if (chan_send(dev, skb)) {
if (chan_send(dev, skb))
return -EBUSY;
}
break;
default:
++chan->ifstats.tx_dropped;
++card->wandev.stats.tx_dropped;
}
} else { /* chan->protocol == ETH_P_X25 */
switch (skb->data[0]) {
case 0: break;
case 1: /* Connect request */
chan_connect(dev);
goto free_packet;
case 2: /* Disconnect request */
chan_disconnect(dev);
goto free_packet;
default:
printk(KERN_INFO
"%s: unknown %d x25-iface request on %s!\n",
card->devname, skb->data[0], dev->name);
++chan->ifstats.tx_errors;
goto free_packet;
}
skb_pull(skb, 1); /* Remove control byte */
reset_timer(dev);
dev->trans_start = jiffies;
dev->tbusy = 1;
if (chan_send(dev, skb)) {
/* prepare for future retransmissions */
skb_push(skb, 1);
return -EBUSY;
}
}
free_packet:
dev_kfree_skb(skb);
return 0;
}
......@@ -733,7 +766,8 @@ static void rx_intr (cycx_t *card, TX25Cmd *cmd)
/* Allocate new socket buffer */
int bufsize = bitm ? dev->mtu : pktlen;
if ((skb = dev_alloc_skb(bufsize +
if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
bufsize +
dev->hard_header_len)) == NULL) {
printk(KERN_INFO "%s: no socket buffers available!\n",
card->devname);
......@@ -742,6 +776,10 @@ static void rx_intr (cycx_t *card, TX25Cmd *cmd)
return;
}
if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
/* 0 = data packet (dev_alloc_skb zeroed skb->data) */
skb_put(skb, 1);
skb->dev = dev;
skb->protocol = htons(chan->protocol);
chan->rx_skb = skb;
......@@ -770,12 +808,11 @@ static void rx_intr (cycx_t *card, TX25Cmd *cmd)
dev->last_rx = jiffies; /* timestamp */
chan->rx_skb = NULL; /* dequeue packet */
skb->protocol = htons(chan->protocol);
skb->dev = dev;
skb->mac.raw = skb->data;
netif_rx(skb);
++chan->ifstats.rx_packets;
chan->ifstats.rx_bytes += skb->len;
skb->mac.raw = skb->data;
netif_rx(skb);
}
/* Connect interrupt handler. */
......@@ -1236,7 +1273,7 @@ static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
* Return: 0 connected
* >0 connection in progress
* <0 failure */
int chan_connect (struct net_device *dev)
static int chan_connect (struct net_device *dev)
{
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
......@@ -1307,6 +1344,10 @@ static void set_chan_state (struct net_device *dev, u8 state)
*(u16*)dev->dev_addr = htons(chan->lcn);
dev->tbusy = 0;
reset_timer(dev);
if (chan->protocol == ETH_P_X25)
chan_x25_send_event(dev, 1);
break;
case WAN_CONNECTING:
......@@ -1329,6 +1370,10 @@ static void set_chan_state (struct net_device *dev, u8 state)
*(unsigned short*)dev->dev_addr = 0;
chan->lcn = 0;
}
if (chan->protocol == ETH_P_X25)
chan_x25_send_event(dev, 2);
dev->tbusy = 0;
break;
}
......@@ -1352,7 +1397,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
* the packet into 'complete sequence' using M-bit.
* 2. When transmission is complete, an event notification should be issued
* to the router. */
int chan_send (struct net_device *dev, struct sk_buff *skb)
static int chan_send (struct net_device *dev, struct sk_buff *skb)
{
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
......@@ -1377,6 +1422,29 @@ int chan_send (struct net_device *dev, struct sk_buff *skb)
return 0;
}
/* Send event (connection, disconnection, etc) to X.25 socket layer */
static void chan_x25_send_event(struct net_device *dev, u8 event)
{
struct sk_buff *skb;
unsigned char *ptr;
if ((skb = dev_alloc_skb(1)) == NULL) {
printk(KERN_ERR __FUNCTION__ ": out of memory\n");
return;
}
ptr = skb_put(skb, 1);
*ptr = event;
skb->dev = dev;
skb->protocol = htons(ETH_P_X25);
skb->mac.raw = skb->data;
skb->pkt_type = PACKET_HOST;
netif_rx(skb);
}
/* Convert line speed in bps to a number used by cyclom 2x code. */
static u8 bps_to_speed_code (u32 bps)
{
......
......@@ -1316,7 +1316,7 @@ static int es1370_mmap(struct file *file, struct vm_area_struct *vma)
db = &s->dma_adc;
} else
return -EINVAL;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
......@@ -1840,7 +1840,7 @@ static int es1370_mmap_dac(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
if ((ret = prog_dmabuf_dac1(s)) != 0)
return ret;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
......
......@@ -1894,7 +1894,7 @@ static int es1371_mmap(struct file *file, struct vm_area_struct *vma)
db = &s->dma_adc;
} else
return -EINVAL;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
......@@ -2415,7 +2415,7 @@ static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
if ((ret = prog_dmabuf_dac1(s)) != 0)
return ret;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
......
......@@ -1199,7 +1199,7 @@ static int solo1_mmap(struct file *file, struct vm_area_struct *vma)
db = &s->dma_adc;
} else
return -EINVAL;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
......
......@@ -1516,7 +1516,7 @@ static int sv_mmap(struct file *file, struct vm_area_struct *vma)
db = &s->dma_adc;
} else
return -EINVAL;
if (vma->vm_offset != 0)
if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
......
......@@ -64,7 +64,7 @@ int expand_fd_array(struct files_struct *files, int nr)
error = -EMFILE;
if (files->max_fds >= NR_OPEN || nr > NR_OPEN)
if (files->max_fds >= NR_OPEN || nr >= NR_OPEN)
goto out;
nfds = files->max_fds;
......@@ -88,7 +88,7 @@ int expand_fd_array(struct files_struct *files, int nr)
if (nfds > NR_OPEN)
nfds = NR_OPEN;
}
} while (nfds < nr);
} while (nfds <= nr);
error = -ENOMEM;
new_fds = alloc_fd_array(nfds);
......
......@@ -371,24 +371,31 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
static struct page *
ncp_get_cache_page(struct inode *inode, unsigned long offset, int used)
{
struct page *page, **hash;
struct page *page_cache;
struct address_space *i_data = &inode->i_data;
struct page *new_page, *page, **hash;
hash = page_hash(&inode->i_data, offset);
page = __find_lock_page(&inode->i_data, offset, hash);
hash = page_hash(i_data, offset);
page = __find_lock_page(i_data, offset, hash);
if (used || page)
return page;
page_cache = page_cache_alloc();
if (page_cache) {
page = page_cache;
if (add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
new_page = page_cache_alloc();
if (!new_page)
return NULL;
for (;;) {
page = new_page;
if (!add_to_page_cache_unique(page, i_data, offset, hash))
break;
page_cache_release(page);
page = NULL;
page_cache_free(page_cache);
page = __find_lock_page(i_data, offset, hash);
if (page) {
page_cache_free(new_page);
break;
}
}
return page;
}
......@@ -460,6 +467,29 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
return NULL;
}
static time_t ncp_obtain_mtime(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
struct inode *parent = dentry->d_parent->d_inode;
struct ncp_server *server = NCP_SERVER(inode);
struct nw_info_struct i;
int len = dentry->d_name.len;
__u8 __name[len + 1];
if (!ncp_conn_valid(server) ||
(inode == inode->i_sb->s_root->d_inode) ||
ncp_is_server_root(parent))
return 0;
memcpy(__name, dentry->d_name.name, len);
io2vol(server, __name, !ncp_preserve_case(parent));
if (ncp_obtain_info(server, parent, __name, &i))
return 0;
return ncp_date_dos2unix(le16_to_cpu(i.modifyTime),
le16_to_cpu(i.modifyDate));
}
static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_dentry;
......@@ -504,25 +534,20 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (!Page_Uptodate(page) || !ctl.head.eof)
goto init_cache;
if ((filp->f_pos == 2) &&
(jiffies - ctl.head.time >= NCP_MAX_AGE(server)))
/* Test, whether inode is changed. */
/* if (...) */
if (filp->f_pos == 2) {
time_t mtime;
if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
goto init_cache;
mtime = ncp_obtain_mtime(dentry);
if ((!mtime) || (mtime != ctl.head.mtime))
goto init_cache;
/* Todo, if inode is unchanged? */
/* else {
ncp_renew_dentries(dentry);
ctl.head.time = jiffies;
} */
}
if (filp->f_pos > ctl.head.end)
goto finished;
/*
* Should we check the complete cache before using?
* If we have big dirs, it can take a long time.
*/
ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
......@@ -574,6 +599,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
ctl.cache = cache;
init_cache:
ncp_invalidate_dircache_entries(dentry);
ctl.head.mtime = ncp_obtain_mtime(dentry);
ctl.head.time = jiffies;
ctl.head.eof = 0;
ctl.fpos = 2;
......
......@@ -223,6 +223,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
}
struct ncp_cache_head {
time_t mtime;
unsigned long time; /* cache age */
unsigned long end; /* last valid fpos in cache */
int eof;
......
......@@ -1200,7 +1200,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *old_inode = old_dentry->d_inode;
struct inode *new_inode = new_dentry->d_inode;
struct dentry *dentry = NULL;
int error, rehash = 0, update = 1;
int error, rehash = 0;
dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
......@@ -1238,21 +1238,16 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/* dentry still busy? */
if (new_dentry->d_count > 1) {
#ifdef NFS_PARANOIA
printk("nfs_rename: target %s/%s busy, d_count=%d\n",
new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
printk("nfs_rename: target %s/%s busy, d_count=%d\n",
new_dentry->d_parent->d_name.name,
new_dentry->d_name.name,
new_dentry->d_count);
#endif
goto out;
}
}
/*
* Check for within-directory rename ... no complications.
*/
if (new_dir == old_dir)
goto do_rename;
/*
* Cross-directory move ...
*
* ... prune child dentries and writebacks if needed.
*/
if (old_dentry->d_count > 1) {
......@@ -1260,40 +1255,26 @@ new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
shrink_dcache_parent(old_dentry);
}
/*
* Now check the use counts ... we can't safely do the
* rename unless we can drop the dentries first.
*/
if (old_dentry->d_count > 1) {
#ifdef NFS_PARANOIA
printk("nfs_rename: old dentry %s/%s busy, d_count=%d\n",
old_dentry->d_parent->d_name.name,old_dentry->d_name.name,old_dentry->d_count);
#endif
goto out;
}
if (new_dentry->d_count > 1 && new_inode) {
#ifdef NFS_PARANOIA
printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
new_dentry->d_parent->d_name.name,
new_dentry->d_name.name,
new_dentry->d_count);
#endif
goto out;
}
d_drop(old_dentry);
update = 0;
do_rename:
/*
* To prevent any new references to the target during the rename,
* we unhash the dentry and free the inode in advance.
*/
if (!list_empty(&new_dentry->d_hash)) {
d_drop(new_dentry);
rehash = update;
rehash = 1;
}
if (new_inode) {
if (new_inode)
d_delete(new_dentry);
}
invalidate_inode_pages(new_dir);
nfs_flush_dircache(new_dir);
......@@ -1302,13 +1283,14 @@ new_dentry->d_parent->d_name.name,new_dentry->d_name.name,new_dentry->d_count);
error = nfs_proc_rename(NFS_DSERVER(old_dentry),
NFS_FH(old_dentry->d_parent), old_dentry->d_name.name,
NFS_FH(new_dentry->d_parent), new_dentry->d_name.name);
if (!error && !S_ISDIR(old_inode->i_mode)) {
NFS_CACHEINV(old_dir);
NFS_CACHEINV(new_dir);
/* Update the dcache if needed */
if (rehash)
d_add(new_dentry, NULL);
if (update)
if (!error && !S_ISDIR(old_inode->i_mode))
d_move(old_dentry, new_dentry);
}
out:
/* new dentry created? */
......
......@@ -719,7 +719,7 @@ int get_unused_fd(void)
* Check whether we need to expand the fd array.
*/
if (fd >= files->max_fds) {
error = expand_fd_array(files, 0);
error = expand_fd_array(files, fd);
if (!error) {
error = -EMFILE;
goto repeat;
......
......@@ -1025,14 +1025,14 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
struct dentry * dentry = NULL;
struct inode * inode = NULL;
kdev_t dev;
int retval = -EPERM;
int retval;
unsigned long flags = 0;
unsigned long page = 0;
struct file dummy; /* allows read-write or read-only flag */
lock_kernel();
if (!capable(CAP_SYS_ADMIN))
goto out;
return -EPERM;
lock_kernel();
if ((new_flags &
(MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
retval = copy_mount_options (data, &page);
......
......@@ -402,7 +402,7 @@ int udf_new_block(const struct inode * inode, Uint16 partition, Uint32 goal, int
got_block:
newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
(group_start << 3);
(sizeof(struct SpaceBitmapDesc) << 3);
tmp = udf_get_pblock(sb, newblock, partition, 0);
if (!udf_clear_bit(bit, bh->b_data))
......@@ -412,16 +412,6 @@ int udf_new_block(const struct inode * inode, Uint16 partition, Uint32 goal, int
}
mark_buffer_dirty(bh, 1);
if (!(bh = getblk(sb->s_dev, tmp, sb->s_blocksize)))
{
udf_debug("cannot get block %d\n", tmp);
unlock_super(sb);
return 0;
}
memset(bh->b_data, 0, sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 1);
udf_release_data(bh);
if (UDF_SB_LVIDBH(sb))
{
......
......@@ -180,7 +180,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
......@@ -207,8 +207,6 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
filp->f_pos = nf_pos;
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &offset, &bh);
liu = le16_to_cpu(cfi.lengthOfImpUse);
lfi = cfi.lengthFileIdent;
if (!fi)
{
......@@ -219,6 +217,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
return 1;
}
liu = le16_to_cpu(cfi.lengthOfImpUse);
lfi = cfi.lengthFileIdent;
if (fibh.sbh == fibh.ebh)
nameptr = fi->fileIdent + liu;
else
......
......@@ -112,7 +112,7 @@ udf_fileident_read(struct inode *dir, int *nf_pos,
(*offset) ++;
if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
*offset = 0;
else
*extoffset = lextoffset;
......@@ -154,7 +154,7 @@ udf_fileident_read(struct inode *dir, int *nf_pos,
(*offset) ++;
if (*offset >= (elen >> dir->i_sb->s_blocksize_bits))
if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
*offset = 0;
else
*extoffset = lextoffset;
......
......@@ -213,6 +213,8 @@ static ssize_t udf_file_write(struct file * file, const char * buf,
if ((bh = udf_expand_adinicb(inode, &i, 0, &err)))
udf_release_data(bh);
else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
return err;
}
retval = generic_file_write(file, buf, count, ppos, block_write_partial_page);
......@@ -294,7 +296,9 @@ static ssize_t udf_file_read_adinicb(struct file * filp, char * buf,
if (!copy_to_user(buf, bh->b_data + pos, left))
*loff += left;
else
return -EFAULT;
left = -EFAULT;
udf_release_data(bh);
return left;
}
......@@ -336,11 +340,11 @@ static ssize_t udf_file_read_adinicb(struct file * filp, char * buf,
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
int result=-1;
int size;
int result = -1;
struct buffer_head *bh = NULL;
struct FileEntry *fe;
Uint16 ident;
long_ad eaicb;
Uint8 *ea = NULL;
if ( permission(inode, MAY_READ) != 0 )
{
......@@ -368,26 +372,42 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
/* ok, we need to read the inode */
bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
if (!bh || ident != TID_FILE_ENTRY)
if (!bh || (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))
{
udf_debug("bread failed (ino=%ld) or ident (%d) != TID_FILE_ENTRY",
udf_debug("bread failed (ino=%ld) or ident (%d) != TID_(EXTENDED_)FILE_ENTRY",
inode->i_ino, ident);
return -EFAULT;
}
if (UDF_I_EXTENDED_FE(inode) == 0)
{
struct FileEntry *fe;
fe = (struct FileEntry *)bh->b_data;
size = le32_to_cpu(fe->lengthExtendedAttr);
eaicb = fe->extendedAttrICB;
if (UDF_I_LENEATTR(inode))
ea = fe->extendedAttr;
}
else
{
struct ExtendedFileEntry *efe;
efe = (struct ExtendedFileEntry *)bh->b_data;
eaicb = efe->extendedAttrICB;
if (UDF_I_LENEATTR(inode))
ea = efe->extendedAttr;
}
switch (cmd)
{
case UDF_GETEASIZE:
if ( (result = verify_area(VERIFY_WRITE, (char *)arg, 4)) == 0)
result= put_user(size, (int *)arg);
result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
break;
case UDF_GETEABLOCK:
if ( (result = verify_area(VERIFY_WRITE, (char *)arg, size)) == 0)
result= copy_to_user((char *)arg, fe->extendedAttr, size);
if ( (result = verify_area(VERIFY_WRITE, (char *)arg, UDF_I_LENEATTR(inode))) == 0)
result = copy_to_user((char *)arg, ea, UDF_I_LENEATTR(inode));
break;
default:
......
......@@ -106,18 +106,48 @@ void udf_delete_inode(struct inode * inode)
void udf_discard_prealloc(struct inode * inode)
{
#ifdef UDF_PREALLOCATE
#if 0
unsigned short total;
lb_addr loc = UDF_I_LOCATION(inode);
lb_addr bloc, eloc;
Uint32 extoffset, elen, nelen, offset, adsize = 0;
struct buffer_head *bh = NULL;
if (UDF_I_PREALLOC_COUNT(inode))
if ((inode->i_size > 0) &&
(inode_bmap(inode, (inode->i_size-1) >> inode->i_sb->s_blocksize_bits,
&bloc, &extoffset, &eloc, &elen, &offset, &bh) ==
EXTENT_RECORDED_ALLOCATED))
{
total = UDF_I_PREALLOC_COUNT(inode);
UDF_I_PREALLOC_COUNT(inode) = 0;
loc.logicalBlockNum = UDF_I_PREALLOC_BLOCK(inode);
udf_free_blocks(inode, loc, 0, total);
if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
adsize = sizeof(long_ad);
else
{
udf_release_data(bh);
return;
}
#endif
nelen = (EXTENT_RECORDED_ALLOCATED << 30) |
((((elen - 1) & ~(inode->i_sb->s_blocksize - 1)) |
((inode->i_size - 1) & (inode->i_sb->s_blocksize - 1))) + 1);
if (nelen != ((EXTENT_RECORDED_ALLOCATED << 30) | elen))
{
extoffset -= adsize;
udf_write_aext(inode, bloc, &extoffset, eloc, nelen, &bh, 1);
}
if (udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 0) ==
EXTENT_NOT_RECORDED_ALLOCATED)
{
udf_free_blocks(inode, eloc, 0, elen >> inode->i_sb->s_blocksize_bits);
memset(&eloc, 0x00, sizeof(lb_addr));
udf_write_aext(inode, bloc, &extoffset, eloc, 0, &bh, 1);
UDF_I_LENALLOC(inode) -= adsize;
udf_write_inode(inode);
}
udf_release_data(bh);
}
else if (bh)
udf_release_data(bh);
#endif
}
......@@ -144,6 +174,9 @@ struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isd
{
UDF_I_EXT0OFFS(inode) = 0;
UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
mark_inode_dirty(inode);
if (inode->i_op == &udf_file_inode_operations_adinicb)
inode->i_op = &udf_file_inode_operations;
return NULL;
}
......@@ -208,6 +241,7 @@ struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isd
memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
memset(&newad, 0x00, sizeof(long_ad));
newad.extLength = UDF_I_EXT0LEN(inode) = inode->i_size;
newad.extLocation.logicalBlockNum = *block;
newad.extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
......@@ -248,7 +282,7 @@ struct buffer_head * udf_getblk(struct inode * inode, long block,
bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize);
if (buffer_new(&dummy))
{
memset(bh->b_data, 0, inode->i_sb->s_blocksize);
memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 1);
}
......@@ -340,6 +374,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
if (pbh != cbh)
{
udf_release_data(pbh);
pbh = cbh;
atomic_inc(&cbh->b_count);
pbloc = cbloc;
}
......@@ -462,7 +497,6 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
{
udf_release_data(pbh);
udf_release_data(cbh);
*err = -ENOSPC;
return NULL;
}
......@@ -488,7 +522,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
udf_release_data(pbh);
if (c == 0 || c == 1)
if (pextoffset == udf_file_entry_alloc_offset(inode))
{
UDF_I_EXT0LEN(inode) = laarr[0].extLength;
UDF_I_EXT0LOC(inode) = laarr[0].extLocation;
......@@ -890,6 +924,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
struct FileEntry *fe;
struct ExtendedFileEntry *efe;
time_t convtime;
long convtime_usec;
int offset, alen;
fe = (struct FileEntry *)bh->b_data;
......@@ -940,21 +975,33 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
if ( udf_stamp_to_time(&convtime, lets_to_cpu(fe->modificationTime)) )
if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(fe->modificationTime)) )
{
inode->i_mtime = convtime;
UDF_I_UMTIME(inode) = convtime_usec;
inode->i_ctime = convtime;
UDF_I_UCTIME(inode) = convtime_usec;
}
else
{
inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UMTIME(inode) = 0;
inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UCTIME(inode) = 0;
}
if ( udf_stamp_to_time(&convtime, lets_to_cpu(fe->accessTime)) )
if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(fe->accessTime)) )
{
inode->i_atime = convtime;
UDF_I_UATIME(inode) = convtime_usec;
}
else
{
inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UATIME(inode) = convtime_usec;
}
UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID);
UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr);
......@@ -967,20 +1014,41 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->modificationTime)) )
if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(efe->modificationTime)) )
{
inode->i_mtime = convtime;
UDF_I_UMTIME(inode) = convtime_usec;
}
else
{
inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UMTIME(inode) = 0;
}
if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->accessTime)) )
if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(efe->accessTime)) )
{
inode->i_atime = convtime;
UDF_I_UATIME(inode) = convtime_usec;
}
else
{
inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UATIME(inode) = 0;
}
if ( udf_stamp_to_time(&convtime, lets_to_cpu(efe->createTime)) )
if ( udf_stamp_to_time(&convtime, &convtime_usec,
lets_to_cpu(efe->createTime)) )
{
inode->i_ctime = convtime;
UDF_I_UCTIME(inode) = convtime_usec;
}
else
{
inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb);
UDF_I_UCTIME(inode) = 0;
}
UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID);
UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr);
......@@ -1764,6 +1832,8 @@ int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
return -1;
}
}
else
atomic_inc(&bh->b_count);
while ((type = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
{
......@@ -1773,6 +1843,7 @@ int udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
nelen = (type << 30) | oelen;
}
udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);
udf_release_data(bh);
return (nelen >> 30);
}
......@@ -1879,12 +1950,12 @@ int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
if (block < 0)
{
printk(KERN_ERR "udf: inode_bmap: block < 0\n");
return 0;
return -1;
}
if (!inode)
{
printk(KERN_ERR "udf: inode_bmap: NULL inode\n");
return 0;
return -1;
}
b_off = block << inode->i_sb->s_blocksize_bits;
......
......@@ -95,16 +95,17 @@ udf_get_last_block(kdev_t dev, int *flags)
int ret;
unsigned long lblock;
unsigned int hbsize = get_hardblocksize(dev);
unsigned int secsize = 512;
unsigned int mult = 0;
unsigned int div = 0;
if (!hbsize)
hbsize = 512;
hbsize = blksize_size[MAJOR(dev)][MINOR(dev)];
if (hbsize > blksize_size[MAJOR(dev)][MINOR(dev)])
mult = hbsize / blksize_size[MAJOR(dev)][MINOR(dev)];
else if (blksize_size[MAJOR(dev)][MINOR(dev)] > hbsize)
div = blksize_size[MAJOR(dev)][MINOR(dev)] / hbsize;
if (secsize > hbsize)
mult = secsize / hbsize;
else if (hbsize > secsize)
div = hbsize / secsize;
if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
{
......@@ -138,7 +139,7 @@ udf_get_last_block(kdev_t dev, int *flags)
}
set_fs(old_fs);
if (!ret)
if (!ret && lblock)
return lblock - 1;
}
else
......
......@@ -66,28 +66,6 @@ udf64_high32(Uint64 indat)
return indat >> 32;
}
/*
* udf_stamp_to_time
*/
time_t *
udf_stamp_to_time(time_t *dest, timestamp src)
{
struct ktm tm;
if ((!dest))
return NULL;
/* this is very rough. need to find source to mktime() */
tm.tm_year=(src.year) - 1900;
tm.tm_mon=(src.month);
tm.tm_mday=(src.day);
tm.tm_hour=src.hour;
tm.tm_min=src.minute;
tm.tm_sec=src.second;
*dest = udf_converttime(&tm);
return dest;
}
uid_t udf_convert_uid(int uidin)
{
if ( uidin == -1 )
......
......@@ -49,141 +49,95 @@ int udf_write_fi(struct FileIdentDesc *cfi, struct FileIdentDesc *sfi,
struct udf_fileident_bh *fibh,
Uint8 *impuse, Uint8 *fileident)
{
struct FileIdentDesc *efi;
Uint16 crclen = fibh->eoffset - fibh->soffset - sizeof(tag);
Uint16 crc;
Uint8 checksum = 0;
int i;
int offset, len;
int padlen = fibh->eoffset - fibh->soffset - cfi->lengthOfImpUse - cfi->lengthFileIdent -
int offset;
Uint16 liu = le16_to_cpu(cfi->lengthOfImpUse);
Uint8 lfi = cfi->lengthFileIdent;
int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
sizeof(struct FileIdentDesc);
crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
sizeof(tag), 0);
efi = (struct FileIdentDesc *)(fibh->ebh->b_data + fibh->soffset);
if (fibh->sbh == fibh->ebh ||
(!fileident &&
(sizeof(struct FileIdentDesc) + (impuse ? cfi->lengthOfImpUse : 0))
<= -fibh->soffset))
{
memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
if (impuse)
memcpy(sfi->impUse, impuse, cfi->lengthOfImpUse);
if (fileident)
memcpy(sfi->fileIdent + cfi->lengthOfImpUse, fileident,
cfi->lengthFileIdent);
/* Zero padding */
memset(sfi->fileIdent + cfi->lengthOfImpUse + cfi->lengthFileIdent, 0,
padlen);
if (fibh->sbh == fibh->ebh)
crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen, 0);
else
{
crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen - fibh->eoffset, 0);
crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
}
sfi->descTag.descCRC = cpu_to_le32(crc);
sfi->descTag.descCRCLength = cpu_to_le16(crclen);
for (i=0; i<16; i++)
if (i != 4)
checksum += ((Uint8 *)&sfi->descTag)[i];
sfi->descTag.tagChecksum = checksum;
mark_buffer_dirty(fibh->sbh, 1);
}
else
{
offset = -fibh->soffset;
len = sizeof(struct FileIdentDesc);
if (len <= offset)
memcpy((Uint8 *)sfi, (Uint8 *)cfi, len);
else
{
memcpy((Uint8 *)sfi, (Uint8 *)cfi, offset);
memcpy(fibh->ebh->b_data, (Uint8 *)cfi + offset, len - offset);
}
offset -= len;
len = cfi->lengthOfImpUse;
offset = fibh->soffset + sizeof(struct FileIdentDesc);
if (impuse)
{
if (offset <= 0)
memcpy(efi->impUse, impuse, len);
else if (sizeof(struct FileIdentDesc) + len <= -fibh->soffset)
memcpy(sfi->impUse, impuse, len);
if (offset + liu < 0)
memcpy((Uint8 *)sfi->impUse, impuse, liu);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, impuse, liu);
else
{
memcpy(sfi->impUse, impuse, offset);
memcpy(efi->impUse + offset, impuse + offset, len - offset);
memcpy((Uint8 *)sfi->impUse, impuse, -offset);
memcpy(fibh->ebh->b_data, impuse - offset, liu + offset);
}
}
offset -= len;
len = cfi->lengthFileIdent;
offset += liu;
if (fileident)
{
if (offset <= 0)
memcpy(efi->fileIdent + cfi->lengthOfImpUse, fileident, len);
if (offset + lfi < 0)
memcpy((Uint8 *)sfi->fileIdent + liu, fileident, lfi);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, fileident, lfi);
else
{
memcpy(sfi->fileIdent + cfi->lengthOfImpUse, fileident, offset);
memcpy(efi->fileIdent + cfi->lengthOfImpUse + offset,
fileident + offset, len - offset);
memcpy((Uint8 *)sfi->fileIdent + liu, fileident, -offset);
memcpy(fibh->ebh->b_data, fileident - offset, lfi + offset);
}
}
/* Zero padding */
memset(efi->fileIdent + cfi->lengthOfImpUse + cfi->lengthFileIdent, 0x00,
padlen);
offset += lfi;
if (sizeof(tag) < -fibh->soffset)
{
crc = udf_crc((Uint8 *)sfi + sizeof(tag), crclen - fibh->eoffset, 0);
crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
}
if (offset + padlen < 0)
memset((Uint8 *)sfi->padding + liu + lfi, 0x00, padlen);
else if (offset >= 0)
memset(fibh->ebh->b_data + offset, 0x00, padlen);
else
crc = udf_crc((Uint8 *)fibh->ebh->b_data + fibh->eoffset - crclen, crclen, 0);
if (&(efi->descTag.descCRC) < (Uint16 *)fibh->ebh->b_data)
{
sfi->descTag.descCRC = cpu_to_le16(crc);
sfi->descTag.descCRCLength = cpu_to_le16(crclen);
memset((Uint8 *)sfi->padding + liu + lfi, 0x00, -offset);
memset(fibh->ebh->b_data, 0x00, padlen + offset);
}
crc = udf_crc((Uint8 *)cfi + sizeof(tag), sizeof(struct FileIdentDesc) -
sizeof(tag), 0);
if (fibh->sbh == fibh->ebh)
crc = udf_crc((Uint8 *)sfi->impUse,
crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
else if (sizeof(struct FileIdentDesc) >= -fibh->soffset)
crc = udf_crc(fibh->ebh->b_data + sizeof(struct FileIdentDesc) + fibh->soffset,
crclen + sizeof(tag) - sizeof(struct FileIdentDesc), crc);
else
{
efi->descTag.descCRC = cpu_to_le16(crc);
efi->descTag.descCRCLength = cpu_to_le16(crclen);
crc = udf_crc((Uint8 *)sfi->impUse,
-fibh->soffset - sizeof(struct FileIdentDesc), crc);
crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
}
cfi->descTag.descCRC = cpu_to_le32(crc);
cfi->descTag.descCRCLength = cpu_to_le16(crclen);
for (i=0; i<16; i++)
{
if (i != 4)
{
if (&(((Uint8 *)&efi->descTag)[i]) < (Uint8 *)fibh->ebh->b_data)
checksum += ((Uint8 *)&sfi->descTag)[i];
else
checksum += ((Uint8 *)&efi->descTag)[i];
}
}
checksum += ((Uint8 *)&cfi->descTag)[i];
if (&(cfi->descTag.tagChecksum) < (Uint8 *)fibh->ebh->b_data)
sfi->descTag.tagChecksum = checksum;
cfi->descTag.tagChecksum = checksum;
if (sizeof(struct FileIdentDesc) <= -fibh->soffset)
memcpy((Uint8 *)sfi, (Uint8 *)cfi, sizeof(struct FileIdentDesc));
else
efi->descTag.tagChecksum = checksum;
{
memcpy((Uint8 *)sfi, (Uint8 *)cfi, -fibh->soffset);
memcpy(fibh->ebh->b_data, (Uint8 *)cfi - fibh->soffset,
sizeof(struct FileIdentDesc) + fibh->soffset);
}
mark_buffer_dirty(fibh->sbh, 1);
if (fibh->sbh != fibh->ebh)
mark_buffer_dirty(fibh->ebh, 1);
}
mark_buffer_dirty(fibh->sbh, 1);
return 0;
}
......@@ -214,7 +168,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
......@@ -240,8 +194,6 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
if (!fi)
{
......@@ -252,6 +204,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
return NULL;
}
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
if (fibh->sbh == fibh->ebh)
{
nameptr = fi->fileIdent + liu;
......@@ -422,7 +377,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
......@@ -446,8 +401,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
if (!fi)
{
......@@ -458,6 +411,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL;
}
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
if (fibh->sbh == fibh->ebh)
nameptr = fi->fileIdent + liu;
else
......@@ -520,6 +476,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
fibh->soffset -= UDF_I_EXT0OFFS(dir);
fibh->eoffset -= UDF_I_EXT0OFFS(dir);
f_pos -= (UDF_I_EXT0OFFS(dir) >> 2);
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
if (!(fibh->sbh = fibh->ebh = udf_expand_adinicb(dir, &block, 1, err)))
return NULL;
......@@ -557,10 +515,12 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
}
else
{
if (elen & (sb->s_blocksize - 1))
elen += nfidlen;
block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits);
elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 1);
block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
}
}
else
......@@ -588,10 +548,16 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL;
}
else
block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
{
elen = ((elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits);
elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 0);
}
*err = -ENOSPC;
if (!(fibh->ebh = udf_getblk(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
{
udf_release_data(bh);
udf_release_data(fibh->sbh);
......@@ -602,7 +568,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) ==
EXTENT_RECORDED_ALLOCATED)
{
block = eloc.logicalBlockNum + (elen >> dir->i_sb->s_blocksize_bits);
block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits);
}
else
block ++;
......@@ -854,7 +821,7 @@ static int empty_dir(struct inode *dir)
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if (++offset < (elen >> dir->i_sb->s_blocksize_bits))
if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
{
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
extoffset -= sizeof(short_ad);
......
......@@ -768,18 +768,20 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
{
struct PrimaryVolDesc *pvoldesc;
time_t recording;
long recording_usec;
struct ustr instr;
struct ustr outstr;
pvoldesc = (struct PrimaryVolDesc *)bh->b_data;
if ( udf_stamp_to_time(&recording, lets_to_cpu(pvoldesc->recordingDateAndTime)) )
if ( udf_stamp_to_time(&recording, &recording_usec,
lets_to_cpu(pvoldesc->recordingDateAndTime)) )
{
timestamp ts;
ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
udf_debug("recording time %ld, %u/%u/%u %u:%u (%x)\n",
recording, ts.year, ts.month, ts.day, ts.hour, ts.minute,
ts.typeAndTimezone);
udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
recording, recording_usec,
ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone);
UDF_SB_RECORDTIME(sb) = recording;
}
......@@ -1397,8 +1399,9 @@ udf_read_super(struct super_block *sb, void *options, int silent)
{
timestamp ts;
udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
udf_info("Mounting volume '%s', timestamp %u/%02u/%u %02u:%02u\n",
UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute);
udf_info("Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
ts.typeAndTimezone);
}
if (!(sb->s_flags & MS_RDONLY))
udf_open_lvid(sb);
......
#ifndef __UDF_DECL_H
#define __UDF_DECL_H
#define UDF_VERSION_NOTICE "v0.8.9"
#define UDF_VERSION_NOTICE "v0.8.9.3"
#ifdef __KERNEL__
......@@ -249,7 +249,7 @@ extern Uint32 udf64_low32(Uint64);
extern Uint32 udf64_high32(Uint64);
extern time_t *udf_stamp_to_time(time_t *, timestamp);
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
extern time_t udf_converttime (struct ktm *);
......
......@@ -42,13 +42,13 @@
#define cpu_to_le32(x) (x)
#define cpu_to_le64(x) (x)
#endif
#endif /* __BYTE_ORDER == 0 */
#endif
#else /* __KERNEL__ */
#ifdef __KERNEL__
#include <linux/string.h>
#endif
#endif /* ! __KERNEL__ */
static inline lb_addr lelb_to_cpu(lb_addr in)
{
......
......@@ -18,16 +18,19 @@
Boston, MA 02111-1307, USA. */
/*
* dgb 10/2/98: ripped this from glibc source to help convert timestamps to unix time
* 10/4/98: added new table-based lookup after seeing how ugly the gnu code is
* dgb 10/02/98: ripped this from glibc source to help convert timestamps to unix time
* 10/04/98: added new table-based lookup after seeing how ugly the gnu code is
* blf 09/27/99: ripped out all the old code and inserted new table from
* John Brockmeyer (without leap second corrections)
* rewrote udf_stamp_to_time and fixed timezone accounting in
udf_time_to_stamp.
*/
/* Assume that leap seconds are possible, unless told otherwise.
If the host has a `zic' command with a `-L leapsecondfilename' option,
then it supports leap seconds; otherwise it probably doesn't. */
#ifndef LEAP_SECONDS_POSSIBLE
#define LEAP_SECONDS_POSSIBLE 1
#endif
/*
* We don't take into account leap seconds. This may be correct or incorrect.
* For more NIST information (especially dealing with leap seconds), see:
* http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
*/
#if defined(__linux__) && defined(__KERNEL__)
#include <linux/types.h>
......@@ -35,30 +38,11 @@
#else
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#endif
#include "udfdecl.h"
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef INT_MIN
#define INT_MIN (~0 << (sizeof (int) * CHAR_BIT - 1))
#endif
#ifndef INT_MAX
#define INT_MAX (~0 - INT_MIN)
#endif
#ifndef TIME_T_MIN
#define TIME_T_MIN (0 < (time_t) -1 ? (time_t) 0 \
: ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
#endif
#ifndef TIME_T_MAX
#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
#endif
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#ifndef __isleap
......@@ -77,70 +61,85 @@ const unsigned short int __mon_yday[2][13] =
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
time_t udf_converttime (struct ktm *);
#ifndef USE_GNU_MKTIME_METHOD
#define MAX_YEAR_SECONDS 68
#define MAX_YEAR_SECONDS 69
#define SPD 0x15180 /*3600*24*/
#define SPY(y,l,s) (SPD * (365*y+l)+s)
time_t year_seconds[MAX_YEAR_SECONDS]= {
0,
/*1971:*/ 31554000, /*1972:*/ 63090000, /*1973:*/ 94712400,
/*1974:*/ 126248400, /*1975:*/ 157784400, /*1976:*/ 189320400,
/*1977:*/ 220942800, /*1978:*/ 252478800, /*1979:*/ 284014800,
/*1980:*/ 315550800, /*1981:*/ 347173200, /*1982:*/ 378709200,
/*1983:*/ 410245200, /*1984:*/ 441781200, /*1985:*/ 473403600,
/*1986:*/ 504939600, /*1987:*/ 536475600, /*1988:*/ 568011600,
/*1989:*/ 599634000, /*1990:*/ 631170000, /*1991:*/ 662706000,
/*1992:*/ 694242000, /*1993:*/ 725864400, /*1994:*/ 757400400,
/*1995:*/ 788936400, /*1996:*/ 820472400, /*1997:*/ 852094800,
/*1998:*/ 883630800, /*1999:*/ 915166800, /*2000:*/ 946702800,
/*2001:*/ 978325200, /*2002:*/ 1009861200, /*2003:*/ 1041397200,
/*2004:*/ 1072933200, /*2005:*/ 1104555600, /*2006:*/ 1136091600,
/*2007:*/ 1167627600, /*2008:*/ 1199163600, /*2009:*/ 1230786000,
/*2010:*/ 1262322000, /*2011:*/ 1293858000, /*2012:*/ 1325394000,
/*2013:*/ 1357016400, /*2014:*/ 1388552400, /*2015:*/ 1420088400,
/*2016:*/ 1451624400, /*2017:*/ 1483246800, /*2018:*/ 1514782800,
/*2019:*/ 1546318800, /*2020:*/ 1577854800, /*2021:*/ 1609477200,
/*2022:*/ 1641013200, /*2023:*/ 1672549200, /*2024:*/ 1704085200,
/*2025:*/ 1735707600, /*2026:*/ 1767243600, /*2027:*/ 1798779600,
/*2028:*/ 1830315600, /*2029:*/ 1861938000, /*2030:*/ 1893474000,
/*2031:*/ 1925010000, /*2032:*/ 1956546000, /*2033:*/ 1988168400,
/*2034:*/ 2019704400, /*2035:*/ 2051240400, /*2036:*/ 2082776400,
/*2037:*/ 2114398800
/*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0),
/*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0),
/*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0),
/*1982*/ SPY(12, 3,0), SPY(13, 3,0), SPY(14, 3,0), SPY(15, 4,0),
/*1986*/ SPY(16, 4,0), SPY(17, 4,0), SPY(18, 4,0), SPY(19, 5,0),
/*1990*/ SPY(20, 5,0), SPY(21, 5,0), SPY(22, 5,0), SPY(23, 6,0),
/*1994*/ SPY(24, 6,0), SPY(25, 6,0), SPY(26, 6,0), SPY(27, 7,0),
/*1998*/ SPY(28, 7,0), SPY(29, 7,0), SPY(30, 7,0), SPY(31, 8,0),
/*2002*/ SPY(32, 8,0), SPY(33, 8,0), SPY(34, 8,0), SPY(35, 9,0),
/*2006*/ SPY(36, 9,0), SPY(37, 9,0), SPY(38, 9,0), SPY(39,10,0),
/*2010*/ SPY(40,10,0), SPY(41,10,0), SPY(42,10,0), SPY(43,11,0),
/*2014*/ SPY(44,11,0), SPY(45,11,0), SPY(46,11,0), SPY(47,12,0),
/*2018*/ SPY(48,12,0), SPY(49,12,0), SPY(50,12,0), SPY(51,13,0),
/*2022*/ SPY(52,13,0), SPY(53,13,0), SPY(54,13,0), SPY(55,14,0),
/*2026*/ SPY(56,14,0), SPY(57,14,0), SPY(58,14,0), SPY(59,15,0),
/*2030*/ SPY(60,15,0), SPY(61,15,0), SPY(62,15,0), SPY(63,16,0),
/*2034*/ SPY(64,16,0), SPY(65,16,0), SPY(66,16,0), SPY(67,17,0),
/*2038*/ SPY(68,17,0)
};
time_t udf_converttime (struct ktm *tm)
#ifdef __KERNEL__
extern struct timezone sys_tz;
#endif
#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
time_t *
udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
{
time_t r;
int yday;
Uint8 type = src.typeAndTimezone >> 12;
Sint16 offset;
if ( !tm )
return -1;
if ( (tm->tm_year+TM_YEAR_BASE < EPOCH_YEAR) ||
(tm->tm_year+TM_YEAR_BASE > EPOCH_YEAR+MAX_YEAR_SECONDS) )
return -1;
r = year_seconds[tm->tm_year-70];
yday = ((__mon_yday[__isleap (tm->tm_year + TM_YEAR_BASE)]
[tm->tm_mon-1])
+ tm->tm_mday - 1);
r += ( ( (yday* 24) + (tm->tm_hour-1) ) * 60 + tm->tm_min ) * 60 + tm->tm_sec;
return r;
}
if (type == 1)
{
offset = src.typeAndTimezone << 4;
/* sign extent offset */
offset = (offset >> 4);
}
else
offset = 0;
#ifdef __KERNEL__
if ((src.year < EPOCH_YEAR) ||
(src.year > EPOCH_YEAR+MAX_YEAR_SECONDS))
{
*dest = -1;
*dest_usec = -1;
return NULL;
}
*dest = year_seconds[src.year - EPOCH_YEAR];
*dest -= offset * 60;
extern struct timezone sys_tz;
yday = ((__mon_yday[__isleap (src.year)]
[src.month-1]) + (src.day-1));
*dest += ( ( (yday* 24) + src.hour ) * 60 + src.minute ) * 60 + src.second;
*dest_usec = src.centiseconds * 10000 + src.hundredsOfMicroseconds * 100 + src.microseconds;
return dest;
}
#define SECS_PER_HOUR (60 * 60)
#define SECS_PER_DAY (SECS_PER_HOUR * 24)
timestamp *
udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
{
long int days, rem, y;
const unsigned short int *ip;
int offset = (-sys_tz.tz_minuteswest + (sys_tz.tz_dsttime ? 60 : 0));
Sint16 offset;
#ifndef __KERNEL__
struct timeval tv;
struct timezone sys_tz;
gettimeofday(&tv, &sys_tz);
#endif
offset = (-sys_tz.tz_minuteswest + (sys_tz.tz_dsttime ? 60 : 0));
if (!dest)
return NULL;
......@@ -183,191 +182,5 @@ udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
dest->hundredsOfMicroseconds * 100);
return dest;
}
#endif
#else
static time_t ydhms_tm_diff (int, int, int, int, int, const struct ktm *);
/* Yield the difference between (YEAR-YDAY HOUR:MIN:SEC) and (*TP),
measured in seconds, ignoring leap seconds.
YEAR uses the same numbering as TM->tm_year.
All values are in range, except possibly YEAR.
If overflow occurs, yield the low order bits of the correct answer. */
static time_t
ydhms_tm_diff (int year, int yday, int hour, int min, int sec, const struct ktm *tp)
{
time_t result;
/* Compute intervening leap days correctly even if year is negative.
Take care to avoid int overflow. time_t overflow is OK, since
only the low order bits of the correct time_t answer are needed.
Don't convert to time_t until after all divisions are done, since
time_t might be unsigned. */
int a4 = (year >> 2) + (TM_YEAR_BASE >> 2) - ! (year & 3);
int b4 = (tp->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (tp->tm_year & 3);
int a100 = a4 / 25 - (a4 % 25 < 0);
int b100 = b4 / 25 - (b4 % 25 < 0);
int a400 = a100 >> 2;
int b400 = b100 >> 2;
int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
time_t years = year - (time_t) tp->tm_year;
time_t days = (365 * years + intervening_leap_days);
result= (60 * (60 * (24 * days + (hour - tp->tm_hour))
+ (min - tp->tm_min))
+ (sec - tp->tm_sec));
#ifdef __KERNEL__
printk(KERN_ERR "udf: ydhms_tm_diff(%d,%d,%d,%d,%d,) returning %ld\n",
year, yday, hour, min, sec, result);
#endif
return result;
}
/* Convert *TP to a time_t value, inverting
the monotonic and mostly-unit-linear conversion function CONVERT.
Use *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
If *OFFSET's guess is correct, only one CONVERT call is needed. */
time_t
udf_converttime (struct ktm *tp)
{
time_t t, dt, t0;
struct ktm tm;
/* The maximum number of probes (calls to CONVERT) should be enough
to handle any combinations of time zone rule changes, solar time,
and leap seconds. Posix.1 prohibits leap seconds, but some hosts
have them anyway. */
int remaining_probes = 4;
/* Time requested. Copy it in case CONVERT modifies *TP; this can
occur if TP is localtime's returned value and CONVERT is localtime. */
int sec = tp->tm_sec;
int min = tp->tm_min;
int hour = tp->tm_hour;
int mday = tp->tm_mday;
int mon = tp->tm_mon;
int year_requested = tp->tm_year;
int isdst = tp->tm_isdst;
/* Ensure that mon is in range, and set year accordingly. */
int mon_remainder = mon % 12;
int negative_mon_remainder = mon_remainder < 0;
int mon_years = mon / 12 - negative_mon_remainder;
int year = year_requested + mon_years;
/* The other values need not be in range:
the remaining code handles minor overflows correctly,
assuming int and time_t arithmetic wraps around.
Major overflows are caught at the end. */
/* Calculate day of year from year, month, and day of month.
The result need not be in range. */
int yday = ((__mon_yday[__isleap (year + TM_YEAR_BASE)]
[mon_remainder + 12 * negative_mon_remainder])
+ mday - 1);
#if LEAP_SECONDS_POSSIBLE
/* Handle out-of-range seconds specially,
since ydhms_tm_diff assumes every minute has 60 seconds. */
int sec_requested = sec;
if (sec < 0)
sec = 0;
if (59 < sec)
sec = 59;
#endif
/* Invert CONVERT by probing. First assume the same offset as last time.
Then repeatedly use the error to improve the guess. */
tm.tm_year = EPOCH_YEAR - TM_YEAR_BASE;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
/*
t0 = ydhms_tm_diff (year, yday, hour, min, sec, &tm);
for (t = t0;
(dt = ydhms_tm_diff (year, yday, hour, min, sec, &tm));
t += dt)
if (--remaining_probes == 0)
return -1;
*/
/* Check whether tm.tm_isdst has the requested value, if any. */
if (0 <= isdst && 0 <= tm.tm_isdst)
{
int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
if (dst_diff)
{
/* Move two hours in the direction indicated by the disagreement,
probe some more, and switch to a new time if found.
The largest known fallback due to daylight savings is two hours:
once, in Newfoundland, 1988-10-30 02:00 -> 00:00. */
time_t ot = t - 2 * 60 * 60 * dst_diff;
while (--remaining_probes != 0)
{
struct ktm otm;
if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
&otm)))
{
t = ot;
tm = otm;
break;
}
if ((ot += dt) == t)
break; /* Avoid a redundant probe. */
}
}
}
#if LEAP_SECONDS_POSSIBLE
if (sec_requested != tm.tm_sec)
{
/* Adjust time to reflect the tm_sec requested, not the normalized value.
Also, repair any damage from a false match due to a leap second. */
t += sec_requested - sec + (sec == 0 && tm.tm_sec == 60);
}
#endif
if (TIME_T_MAX / INT_MAX / 366 / 24 / 60 / 60 < 3)
{
/* time_t isn't large enough to rule out overflows in ydhms_tm_diff,
so check for major overflows. A gross check suffices,
since if t has overflowed, it is off by a multiple of
TIME_T_MAX - TIME_T_MIN + 1. So ignore any component of
the difference that is bounded by a small value. */
double dyear = (double) year_requested + mon_years - tm.tm_year;
double dday = 366 * dyear + mday;
double dsec = 60 * (60 * (24 * dday + hour) + min) + sec_requested;
if (TIME_T_MAX / 3 - TIME_T_MIN / 3 < (dsec < 0 ? - dsec : dsec))
return -1;
}
*tp = tm;
#ifdef __KERNEL__
udf_debug("returning %ld\n", t);
#endif
return t;
}
#endif
#ifdef INCLUDE_PRINT_KTM
static void
print_ktm (struct ktm *tp)
{
#ifdef __KERNEL__
udf_debug(
#else
printf(
#endif
"%04d-%02d-%02d %02d:%02d:%02d isdst %d",
tp->tm_year + TM_YEAR_BASE, tp->tm_mon + 1, tp->tm_mday,
tp->tm_hour, tp->tm_min, tp->tm_sec, tp->tm_isdst);
}
#endif
/* EOF */
......@@ -11,13 +11,14 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
* 1999/10/23 acme cycxhw_t cleanup
* 1999/01/03 acme more judicious use of data types...
* uclong, ucchar, etc deleted, the u8, u16, u32
* types are the portable way to go.
* 1999/01/03 acme judicious use of data types... u16, u32, etc
* Dec 26, 1998 Arnaldo FIXED_BUFFERS, CONF_OFFSET,
* 1998/12/26 acme FIXED_BUFFERS, CONF_OFFSET,
* removal of cy_read{bwl}
* Aug 08, 1998 Arnaldo Initial version.
* 1998/08/08 acme Initial version.
*/
#ifndef _CYCX_DRV_H
#define _CYCX_DRV_H
......@@ -43,22 +44,19 @@
/* Adapter hardware configuration. Pointer to this structure is passed to all
* APIs. */
typedef struct cycxhw {
u32 type; /* adapter type */
u32 fwid; /* firmware ID */
int irq; /* interrupt request level */
u32 dpmbase; /* dual-port memory base */
u32 dpmsize; /* dual-port memory size */
u32 pclk; /* CPU clock rate, kHz */
u32 memory; /* memory size */
u32 reserved[5];
} cycxhw_t;
/* Function Prototypes */
extern int cycx_setup (cycxhw_t *hw, void *sfm, u32 len);
extern int cycx_down (cycxhw_t *hw);
extern int cycx_inten (cycxhw_t *hw);
extern int cycx_intr (cycxhw_t *hw);
extern int cycx_peek (cycxhw_t *hw, u32 addr, void *buf, u32 len);
extern int cycx_poke (cycxhw_t *hw, u32 addr, void *buf, u32 len);
extern int cycx_exec (u32 addr);
extern void cycx_inten (cycxhw_t *hw);
extern void cycx_intr (cycxhw_t *hw);
#endif /* _CYCX_DRV_H */
......@@ -13,6 +13,7 @@
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Florian La Roche,
* Jonathan Layes <layes@loran.com>
* Arnaldo Carvalho de Melo <acme@conectiva.com.br> ARPHRD_HWX25
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -47,6 +48,7 @@
#define ARPHRD_ADAPT 264
#define ARPHRD_ROSE 270
#define ARPHRD_X25 271 /* CCITT X.25 */
#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */
#define ARPHRD_PPP 512
#define ARPHRD_HDLC 513 /* (Cisco) HDLC */
#define ARPHRD_LAPB 516 /* LAPB */
......
......@@ -54,15 +54,23 @@
#ifdef __KERNEL__
#include <linux/types.h>
#define Uint8 __u8
#define Sint8 __s8
#define Uint16 __u16
#define Sint16 __s16
#define Uint32 __u32
#define Sint32 __s32
#define Uint64 __u64
#define Sint64 __s64
typedef Uint8 dstring;
#else
#define Uint8 unsigned char
#define Sint8 char
#define Uint16 unsigned short
#define Sint16 short
#define Uint32 unsigned int
#define Sint32 int
#define Uint64 unsigned long long
#define Sint64 long long
typedef Uint8 dstring;
#endif
......
......@@ -30,8 +30,8 @@
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
#define UDF_DEFAULT_PREALLOC_DIR_BLOCKS 0
#define UDFFS_DATE "99/09/02"
#define UDFFS_VERSION "0.8.9"
#define UDFFS_DATE "99/10/29"
#define UDFFS_VERSION "0.8.9.3"
#define UDFFS_DEBUG
#ifdef UDFFS_DEBUG
......
......@@ -294,6 +294,7 @@ rpc_call_setup(struct rpc_task *task, u32 proc,
task->tk_flags |= flags;
/* Increment call count */
if (task->tk_proc < task->tk_client->cl_maxproc)
rpcproc_count(task->tk_client, proc)++;
}
......@@ -319,9 +320,14 @@ static void
call_bind(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_xprt *xprt = clnt->cl_xprt;
if (xprt->stream && !xprt->connected)
task->tk_action = call_reconnect;
else
task->tk_action = call_reserve;
task->tk_status = 0;
if (!clnt->cl_port)
rpc_getport(task, clnt);
}
......@@ -340,6 +346,7 @@ call_reserve(struct rpc_task *task)
clnt->cl_protname, clnt->cl_server,
clnt->cl_softrtry? "giving up" : "retrying");
if (!clnt->cl_softrtry) {
task->tk_action = call_bind;
rpc_delay(task, 5*HZ);
return;
}
......@@ -376,25 +383,27 @@ call_reserveresult(struct rpc_task *task)
if (task->tk_status >= 0) {
task->tk_action = call_allocate;
goto out;
} else if (task->tk_status == -EAGAIN) {
return;
}
switch (task->tk_status) {
case -EAGAIN:
case -ENOBUFS:
task->tk_timeout = task->tk_client->cl_timeout.to_resrvval;
task->tk_status = 0;
xprt_reserve(task);
goto out;
} else if (task->tk_status == -ETIMEDOUT) {
task->tk_action = call_reserve;
break;
case -ETIMEDOUT:
dprintk("RPC: task timed out\n");
task->tk_action = call_timeout;
goto out;
} else {
break;
default:
task->tk_action = NULL;
}
if (!task->tk_rqstp) {
printk("RPC: task has no request, exit EIO\n");
rpc_exit(task, -EIO);
}
out:
return;
}
}
/*
......@@ -424,7 +433,7 @@ call_allocate(struct rpc_task *task)
if (!signalled()) {
xprt_release(task);
task->tk_action = call_reserve;
rpc_delay(task, HZ);
rpc_delay(task, HZ>>4);
return;
}
......@@ -477,7 +486,7 @@ call_encode(struct rpc_task *task)
printk("RPC: call_header failed, exit EIO\n");
rpc_exit(task, -EIO);
} else
if ((status = encode(req, p, task->tk_argp)) < 0) {
if (encode && (status = encode(req, p, task->tk_argp)) < 0) {
printk(KERN_WARNING "%s: can't encode arguments: %d\n",
clnt->cl_protname, -status);
rpc_exit(task, status);
......@@ -508,19 +517,16 @@ call_receive(struct rpc_task *task)
task->tk_pid, task->tk_status);
task->tk_action = call_status;
/* In case of error, evaluate status */
if (task->tk_status < 0)
return;
/* Need to ensure cleanups are performed by xprt_receive_status() */
xprt_receive(task);
/* If we have no decode function, this means we're performing
* a void call (a la lockd message passing). */
if (!rpcproc_decode(task->tk_client, task->tk_proc)) {
rpc_remove_wait_queue(task); /* remove from xprt_pending */
task->tk_action = NULL;
return;
}
xprt_receive(task);
}
/*
......@@ -530,6 +536,7 @@ static void
call_status(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
struct rpc_xprt *xprt = clnt->cl_xprt;
struct rpc_rqst *req;
int status = task->tk_status;
......@@ -538,28 +545,48 @@ call_status(struct rpc_task *task)
if (status >= 0) {
task->tk_action = call_decode;
} else if (status == -ETIMEDOUT) {
}
task->tk_status = 0;
req = task->tk_rqstp;
switch(status) {
case -ETIMEDOUT:
task->tk_action = call_timeout;
} else if (status == -EAGAIN) {
if (!(req = task->tk_rqstp))
break;
case -EAGAIN:
if (!req)
task->tk_action = call_reserve;
else if (!task->tk_buffer)
task->tk_action = call_allocate;
else if (req->rq_damaged)
else if (req->rq_damaged) {
task->tk_action = call_encode;
else
clnt->cl_stats->rpcretrans++;
} else {
task->tk_action = call_transmit;
} else if (status == -ENOTCONN) {
task->tk_action = call_reconnect;
} else if (status == -ECONNREFUSED && clnt->cl_autobind) {
task->tk_action = call_bind;
clnt->cl_stats->rpcretrans++;
}
break;
case -ECONNREFUSED:
case -ENOTCONN:
if (clnt->cl_autobind || !clnt->cl_port) {
clnt->cl_port = 0;
} else {
task->tk_action = call_bind;
} else if (xprt->stream)
task->tk_action = call_reconnect;
else {
rpc_delay(task, 5*HZ); /* Hope it all wears off */
if (req->rq_damaged)
task->tk_action = call_encode;
else
task->tk_action = call_transmit;
clnt->cl_stats->rpcretrans++;
}
break;
default:
if (clnt->cl_chatty)
printk("%s: RPC call returned error %d\n",
clnt->cl_protname, -status);
task->tk_action = NULL;
return;
rpc_exit(task, status);
}
}
......@@ -610,6 +637,8 @@ call_timeout(struct rpc_task *task)
minor_timeout:
if (!clnt->cl_port) {
task->tk_action = call_bind;
} else if (clnt->cl_xprt->stream && !clnt->cl_xprt->connected) {
task->tk_action = call_reconnect;
} else if (!req) {
task->tk_action = call_reserve;
} else if (req->rq_damaged) {
......@@ -628,14 +657,12 @@ call_timeout(struct rpc_task *task)
static void
call_reconnect(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
dprintk("RPC: %4d call_reconnect status %d\n",
task->tk_pid, task->tk_status);
if (task->tk_status == 0) {
task->tk_action = call_status;
task->tk_status = -EAGAIN;
return;
}
task->tk_client->cl_stats->netreconn++;
task->tk_action = call_reserve;
task->tk_status = 0;
clnt->cl_stats->netreconn++;
xprt_reconnect(task);
}
......@@ -685,6 +712,8 @@ call_decode(struct rpc_task *task)
}
task->tk_action = NULL;
if (decode)
task->tk_status = decode(req, p, task->tk_resp);
dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
task->tk_status);
......@@ -714,11 +743,10 @@ call_refreshresult(struct rpc_task *task)
dprintk("RPC: %4d call_refreshresult (status %d)\n",
task->tk_pid, task->tk_status);
if (task->tk_status < 0) {
task->tk_status = -EACCES;
task->tk_action = NULL;
} else
task->tk_action = call_reserve;
if (task->tk_status < 0)
rpc_exit(task, -EACCES);
else
task->tk_action = call_bind;
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment