static int floppy_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long param) { struct floppy_state *fs = bdev->bd_disk->private_data; int err; if ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (fs->mdev->media_bay && check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; switch (cmd) { case FDEJECT: if (fs->ref_count != 1) return -EBUSY; err = fd_eject(fs); return err; case FDGETPRM: if (copy_to_user((void __user *) param, &floppy_type, sizeof(struct floppy_struct))) return -EFAULT; return 0; } return -ENOTTY; }
static void do_fd_request(struct request_queue * q) { int i; for(i=0; i<floppy_count; i++) { struct floppy_state *fs = &floppy_states[i]; if (fs->mdev->media_bay && check_media_bay(fs->mdev->media_bay) != MB_FD) continue; start_request(fs); } }
static void do_fd_request(request_queue_t * q) { int i; for(i=0;i<floppy_count;i++) { if (floppy_states[i].media_bay && check_media_bay(floppy_states[i].media_bay, MB_FD)) continue; start_request(&floppy_states[i]); } sti(); }
static void do_fd_request(request_queue_t * q) { int i; for(i=0;i<floppy_count;i++) { #ifdef CONFIG_PMAC_MEDIABAY if (floppy_states[i].media_bay && check_media_bay(floppy_states[i].media_bay, MB_FD)) continue; #endif /* CONFIG_PMAC_MEDIABAY */ start_request(&floppy_states[i]); } }
static void pmac_ide_init_dev(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; pmac_ide_hwif_t *pmif = dev_get_drvdata(hwif->gendev.parent); if (on_media_bay(pmif)) { if (check_media_bay(pmif->mdev->media_bay) == MB_CD) { drive->dev_flags &= ~IDE_DFLAG_NOPROBE; return; } drive->dev_flags |= IDE_DFLAG_NOPROBE; } }
static int floppy_revalidate(struct gendisk *disk) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw; int ret, n; if (fs->mdev->media_bay && check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; sw = fs->swim3; grab_drive(fs, revalidating, 0); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE); swim3_action(fs, MOTOR_ON); /* necessary? */ fs->write_prot = -1; fs->cur_cyl = -1; mdelay(1); for (n = HZ; n > 0; --n) { if (swim3_readbit(fs, SEEK_COMPLETE)) break; if (signal_pending(current)) break; swim3_select(fs, RELAX); schedule_timeout_interruptible(1); } ret = swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0; if (ret) swim3_action(fs, MOTOR_OFF); else { fs->ejected = 0; swim3_action(fs, SETMFM); } swim3_select(fs, RELAX); release_drive(fs); return ret; }
static int floppy_open(struct block_device *bdev, fmode_t mode) { struct floppy_state *fs = bdev->bd_disk->private_data; struct swim3 __iomem *sw = fs->swim3; int n, err = 0; if (fs->ref_count == 0) { if (fs->mdev->media_bay && check_media_bay(fs->mdev->media_bay) != MB_FD) return -ENXIO; out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); out_8(&sw->control_bic, 0xff); out_8(&sw->mode, 0x95); udelay(10); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); swim3_action(fs, MOTOR_ON); fs->write_prot = -1; fs->cur_cyl = -1; for (n = 0; n < 2 * HZ; ++n) { if (n >= HZ/30 && swim3_readbit(fs, SEEK_COMPLETE)) break; if (signal_pending(current)) { err = -EINTR; break; } swim3_select(fs, RELAX); schedule_timeout_interruptible(1); } if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0)) err = -ENXIO; swim3_action(fs, SETMFM); swim3_select(fs, RELAX); } else if (fs->ref_count == -1 || mode & FMODE_EXCL) return -EBUSY; if (err == 0 && (mode & FMODE_NDELAY) == 0 && (mode & (FMODE_READ|FMODE_WRITE))) { check_disk_change(bdev); if (fs->ejected) err = -ENXIO; } if (err == 0 && (mode & FMODE_WRITE)) { if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) err = -EROFS; } if (err) { if (fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE); swim3_select(fs, RELAX); } return err; } if (mode & FMODE_EXCL) fs->ref_count = -1; else ++fs->ref_count; return 0; }
static void start_request(struct floppy_state *fs) { struct request *req; unsigned long x; swim3_dbg("start request, initial state=%d\n", fs->state); if (fs->state == idle && fs->wanted) { fs->state = available; wake_up(&fs->wait); return; } while (fs->state == idle) { swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req); if (!fs->cur_req) { fs->cur_req = blk_fetch_request(disks[fs->index]->queue); swim3_dbg(" fetched request %p\n", fs->cur_req); if (!fs->cur_req) break; } req = fs->cur_req; if (fs->mdev->media_bay && check_media_bay(fs->mdev->media_bay) != MB_FD) { swim3_dbg("%s", " media bay absent, dropping req\n"); swim3_end_request(fs, BLK_STS_IOERR, 0); continue; } #if 0 /* This is really too verbose */ swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", req->rq_disk->disk_name, req->cmd, (long)blk_rq_pos(req), blk_rq_sectors(req), bio_data(req->bio)); swim3_dbg(" current_nr_sectors=%u\n", blk_rq_cur_sectors(req)); #endif if (blk_rq_pos(req) >= fs->total_secs) { swim3_dbg(" pos out of bounds (%ld, max is %ld)\n", (long)blk_rq_pos(req), (long)fs->total_secs); swim3_end_request(fs, BLK_STS_IOERR, 0); continue; } if (fs->ejected) { swim3_dbg("%s", " disk ejected\n"); swim3_end_request(fs, BLK_STS_IOERR, 0); continue; } if (rq_data_dir(req) == WRITE) { if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) { swim3_dbg("%s", " try to write, disk write protected\n"); swim3_end_request(fs, BLK_STS_IOERR, 0); continue; } } /* Do not remove the cast. blk_rq_pos(req) is now a * sector_t and can be 64 bits, but it will never go * past 32 bits for this driver anyway, so we can * safely cast it down and not have to do a 64/32 * division */ fs->req_cyl = ((long)blk_rq_pos(req)) / fs->secpercyl; x = ((long)blk_rq_pos(req)) % fs->secpercyl; fs->head = x / fs->secpertrack; fs->req_sector = x % fs->secpertrack + 1; fs->state = do_transfer; fs->retries = 0; act(fs); } }
static int swim3_add_device(struct macio_dev *mdev, int index) { struct device_node *swim = mdev->ofdev.dev.of_node; struct floppy_state *fs = &floppy_states[index]; int rc = -EBUSY; /* Do this first for message macros */ memset(fs, 0, sizeof(*fs)); fs->mdev = mdev; fs->index = index; /* Check & Request resources */ if (macio_resource_count(mdev) < 2) { swim3_err("%s", "No address in device-tree\n"); return -ENXIO; } if (macio_irq_count(mdev) < 1) { swim3_err("%s", "No interrupt in device-tree\n"); return -ENXIO; } if (macio_request_resource(mdev, 0, "swim3 (mmio)")) { swim3_err("%s", "Can't request mmio resource\n"); return -EBUSY; } if (macio_request_resource(mdev, 1, "swim3 (dma)")) { swim3_err("%s", "Can't request dma resource\n"); macio_release_resource(mdev, 0); return -EBUSY; } dev_set_drvdata(&mdev->ofdev.dev, fs); if (mdev->media_bay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); fs->state = idle; fs->swim3 = (struct swim3 __iomem *) ioremap(macio_resource_start(mdev, 0), 0x200); if (fs->swim3 == NULL) { swim3_err("%s", "Couldn't map mmio registers\n"); rc = -ENOMEM; goto out_release; } fs->dma = (struct dbdma_regs __iomem *) ioremap(macio_resource_start(mdev, 1), 0x200); if (fs->dma == NULL) { swim3_err("%s", "Couldn't map dma registers\n"); iounmap(fs->swim3); rc = -ENOMEM; goto out_release; } fs->swim3_intr = macio_irq(mdev, 0); fs->dma_intr = macio_irq(mdev, 1); fs->cur_cyl = -1; fs->cur_sector = -1; fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; init_waitqueue_head(&fs->wait); fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); fs->dma_cmd[1].command = cpu_to_le16(DBDMA_STOP); if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD) swim3_mb_event(mdev, MB_FD); if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { swim3_err("%s", "Couldn't request interrupt\n"); pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); goto out_unmap; return -EBUSY; } timer_setup(&fs->timeout, NULL, 0); swim3_info("SWIM3 floppy controller %s\n", mdev->media_bay ? "in media bay" : ""); return 0; out_unmap: iounmap(fs->dma); iounmap(fs->swim3); out_release: macio_release_resource(mdev, 0); macio_release_resource(mdev, 1); return rc; }