patch-2.4.20 linux-2.4.20/drivers/s390/char/tubfs.c
Next file: linux-2.4.20/drivers/s390/char/tubio.h
Previous file: linux-2.4.20/drivers/s390/char/tuball.c
Back to the patch index
Back to the overall index
- Lines: 231
- Date:
Thu Nov 28 15:53:14 2002
- Orig file:
linux-2.4.19/drivers/s390/char/tubfs.c
- Orig date:
Fri Sep 7 09:28:38 2001
diff -urN linux-2.4.19/drivers/s390/char/tubfs.c linux-2.4.20/drivers/s390/char/tubfs.c
@@ -42,11 +42,11 @@
{
char name[16];
- sprintf(name, "tub%.3x", tubp->devno);
+ sprintf(name, "tub%.4x", tubp->devno);
devfs_register(fs3270_devfs_dir, name, DEVFS_FL_DEFAULT,
IBM_FS3270_MAJOR, tubp->minor,
S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL);
- sprintf(name, "tty%.3x", tubp->devno);
+ sprintf(name, "tty%.4x", tubp->devno);
tty_register_devfs_name(&tty3270_driver, 0, tubp->minor,
fs3270_devfs_dir, name);
}
@@ -56,12 +56,12 @@
char name[16];
devfs_handle_t handle;
- sprintf(name, "tub%.3x", tubp->devno);
+ sprintf(name, "tub%.4x", tubp->devno);
handle = devfs_find_handle (fs3270_devfs_dir, name,
IBM_FS3270_MAJOR, tubp->minor,
DEVFS_SPECIAL_CHR, 0);
devfs_unregister (handle);
- sprintf(name, "tty%.3x", tubp->devno);
+ sprintf(name, "tty%.4x", tubp->devno);
handle = devfs_find_handle (fs3270_devfs_dir, name,
IBM_TTY3270_MAJOR, tubp->minor,
DEVFS_SPECIAL_CHR, 0);
@@ -241,12 +241,18 @@
{
long flags;
tub_t *tubp;
+ addr_t *ip;
tubp = data;
TUBLOCK(tubp->irq, flags);
tubp->flags &= ~TUB_BHPENDING;
if (tubp->wbuf) { /* if we were writing */
+ for (ip = tubp->wbuf; ip < tubp->wbuf+33; ip++) {
+ if (*ip == 0)
+ break;
+ kfree(phys_to_virt(*ip));
+ }
kfree(tubp->wbuf);
tubp->wbuf = NULL;
}
@@ -289,8 +295,6 @@
#define DEV_UE_BUSY \
(DEV_STAT_CHN_END | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP)
- tubp->dstat = dsp->dstat;
-
#ifdef RBHNOTYET
/* XXX needs more work; must save 2d arg to fs370_io() */
/* Handle CE-DE-UE and subsequent UDE */
@@ -373,47 +377,77 @@
ccw1_t *cp;
int rc;
long flags;
+ addr_t *idalp, *ip;
+ char *tp;
+ int count, piece;
+ int size;
+
+ if (len == 0 || len > 65535) {
+ return -EINVAL;
+ }
if ((tubp = INODE2TUB((struct inode *)fp->private_data)) == NULL)
return -ENODEV;
- if ((rc = fs3270_wait(tubp, &flags)) != 0) {
- TUBUNLOCK(tubp->irq, flags);
- return rc;
+
+ if ((ip = idalp = idal_alloc(33)) == NULL)
+ return -EFAULT;
+ memset(idalp, 0, 33 * sizeof *idalp);
+ count = len;
+ while (count) {
+ piece = MIN(count, 0x800);
+ size = count == len? piece: 0x800;
+ if ((kp = kmalloc(size, GFP_KERNEL|GFP_DMA)) == NULL) {
+ len = -ENOMEM;
+ goto do_cleanup;
+ }
+ *ip++ = virt_to_phys(kp);
+ count -= piece;
}
- kp = kmalloc(len, GFP_KERNEL|GFP_DMA);
- if (kp == NULL) {
+ if ((rc = fs3270_wait(tubp, &flags)) != 0) {
TUBUNLOCK(tubp->irq, flags);
- return -ENOMEM;
+ len = rc;
+ goto do_cleanup;
}
-
cp = &tubp->rccw;
if (tubp->icmd == 0 && tubp->ocmd != 0) tubp->icmd = 6;
cp->cmd_code = tubp->icmd?:2;
- cp->flags = CCW_FLAG_SLI;
+ cp->flags = CCW_FLAG_SLI | CCW_FLAG_IDA;
cp->count = len;
- cp->cda = virt_to_phys(kp);
+ cp->cda = virt_to_phys(idalp);
tubp->flags |= TUB_RDPENDING;
TUBUNLOCK(tubp->irq, flags);
if ((rc = fs3270_wait(tubp, &flags)) != 0) {
tubp->flags &= ~TUB_RDPENDING;
+ len = rc;
TUBUNLOCK(tubp->irq, flags);
- kfree(kp);
- return rc;
+ goto do_cleanup;
}
+ TUBUNLOCK(tubp->irq, flags);
len -= tubp->cswl;
- TUBUNLOCK(tubp->irq, flags);
- if (tubdebug & 1)
- printk(KERN_DEBUG "minor %d: %.8x %.8x %.8x %.8x\n",
- tubp->minor,
- *(int*)((long)kp + 0),
- *(int*)((long)kp + 4),
- *(int*)((long)kp + 8),
- *(int*)((long)kp + 12));
- copy_to_user(dp, kp, len);
- kfree(kp);
+ count = len;
+ tp = dp;
+ ip = idalp;
+ while (count) {
+ piece = MIN(count, 0x800);
+ if (copy_to_user(tp, phys_to_virt(*ip), piece) != 0) {
+ len = -EFAULT;
+ goto do_cleanup;
+ }
+ count -= piece;
+ tp += piece;
+ ip++;
+ }
+
+do_cleanup:
+ for (ip = idalp; ip < idalp+33; ip++) {
+ if (*ip == 0)
+ break;
+ kfree(phys_to_virt(*ip));
+ }
+ idal_free(idalp);
return len;
}
@@ -428,34 +462,64 @@
int rc;
long flags;
void *kb;
+ addr_t *idalp, *ip;
+ int count, piece;
+ int index;
+ int size;
+
+ if (len > 65535 || len == 0)
+ return -EINVAL;
/* Locate the tube */
if ((tubp = INODE2TUB((struct inode *)fp->private_data)) == NULL)
return -ENODEV;
- /* Copy data to write from user address space */
- if ((kb = kmalloc(len, GFP_KERNEL|GFP_DMA)) == NULL)
- return -ENOMEM;
- if (copy_from_user(kb, dp, len) != 0) {
- kfree(kb);
+ if ((ip = idalp = idal_alloc(33)) == NULL)
return -EFAULT;
+ memset(idalp, 0, 33 * sizeof *idalp);
+
+ count = len;
+ index = 0;
+ while (count) {
+ piece = MIN(count, 0x800);
+ size = count == len? piece: 0x800;
+ if ((kb = kmalloc(size, GFP_KERNEL|GFP_DMA)) == NULL) {
+ len = -ENOMEM;
+ goto do_cleanup;
+ }
+ *ip++ = virt_to_phys(kb);
+ if (copy_from_user(kb, &dp[index], piece) != 0) {
+ len = -EFAULT;
+ goto do_cleanup;
+ }
+ count -= piece;
+ index += piece;
}
/* Wait till tube's not working or signal is pending */
if ((rc = fs3270_wait(tubp, &flags))) {
+ len = rc;
TUBUNLOCK(tubp->irq, flags);
- kfree(kb);
- return rc;
+ goto do_cleanup;
}
- /* Make CCW and start I/O. Back end will free buffer. */
- tubp->wbuf = kb;
+ /* Make CCW and start I/O. Back end will free buffers & idal. */
+ tubp->wbuf = idalp;
cp = &tubp->wccw;
cp->cmd_code = tubp->ocmd? tubp->ocmd == 5? 13: tubp->ocmd: 1;
- cp->flags = CCW_FLAG_SLI;
+ cp->flags = CCW_FLAG_SLI | CCW_FLAG_IDA;
cp->count = len;
cp->cda = virt_to_phys(tubp->wbuf);
fs3270_io(tubp, cp);
TUBUNLOCK(tubp->irq, flags);
return len;
+
+do_cleanup:
+ for (ip = idalp; ip < idalp+33; ip++) {
+ if (*ip == 0)
+ break;
+ kfree(phys_to_virt(*ip));
+ }
+ idal_free(idalp);
+ return len;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)