On Tue, Jun 02, 2020 at 09:32:29AM +1000, Finn Thain wrote:
I'm hoping that the SWIM IOP can be used in bypass mode, so it could be used with the swim.c driver. I haven't been able to make that work yet.
Putting the IOP in bypass mode would have a couple issues. The obvious one is that it will break ADB (and because the shift register attached to the ADB transceiver is part of the IOP chip itself, there's not an easy fix for that), but there's also some strangeness in the way the SWIM chip is attached to the IOP chip that looks like it might break a few things. In particular, it looks like they only enabled using the SWIM chip in ISM mode and not IWM mode. The notes I have imply that the normal Mac floppy driver didn't work on a IIfx even in bypass mode. In particular, note the direct use of a GPIO line on VIA1 in swim_select in drivers/block/swim.c. That won't work on an IOP based system as that input line to SWIM doesn't appear to be hooked up to anything that can be accessed directly. Here's the way it's put in _Guide to the Macintosh Family Hardware_ (Second Edition), on page 155: "An IOP provides the state-control line SEL to the floppy disk drives. Among other functions, this line selects which of the two heads is to be used in a double-sided floppy disk drive." The bit in VIA1 register A that is normally the "vHeadSel" line is explicitly listed as "Reserved" on the IIfx. It's definitely possible to access and drive the SWIM chip in bypass mode, but that doesn't mean it's as transparent as for the SCC driver. Apparently this external input line is not strictly required when the SWIM chip is running in ISM mode. However, our driver appears to force the chip into ISM mode and yet still depends on this input line.
You may want to send the patch to the mailing list anyway. Or maybe send it to the linux-mac68k bug tracker on sourceforge.
I've pasted it in here so there is a record of it. The fixes are to properly handle multiple drives (my IIfx has two floppy drives installed) and to initialize and handle the auto-polling of drive status properly. Brad Boyer flar@xxxxxxxxxxxxx --- swim_iop.c-cvs Fri Jul 19 22:49:23 2002 +++ swim_iop.c Sat Jul 27 00:51:30 2002 @@ -5,12 +5,15 @@ * Written by Joshua M. Thompson (funaho@xxxxxxxxx) * based on the SWIM3 driver (c) 1996 by Paul Mackerras. * + * Misc fixes by Brad A. Boyer (flar@xxxxxxxxxxxxx) + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * 1999-06-12 (jmt) - Initial implementation. + * 2002-07-26 (bab) - Fixed drive number storage and enabled status updates */ /* @@ -148,6 +151,7 @@ int swimiop_init(void) { volatile struct swim_iop_req req; + struct swimcmd_startpoll *poll = (struct swimcmd_startpoll *) &req.command[0]; struct swimcmd_status *cmd = (struct swimcmd_status *) &req.command[0]; struct swim_drvstatus *ds = &cmd->status; struct floppy_state *fs; @@ -175,6 +179,19 @@ return -EBUSY; } + printk(KERN_ERR "SWIM_IOP: setting up automatic notification.\n"); + + swimiop_init_request(&req); + poll->code = CMD_START_POLL; + if (swimiop_send_request(&req) != 0) { + printk(KERN_ERR "SWIM_IOP: failed to request autonotify.\n"); + } else { + while (!req.complete); + if (cmd->error != 0) { + printk(KERN_ERR "SWIM_IOP: notify setup failed.\n"); + } + } + printk(KERN_ERR "SWIM_IOP: probing for installed drives.\n"); for (i = 0 ; i < MAX_FLOPPIES ; i++) { @@ -199,6 +216,7 @@ ds->info.secondary? "secondary" : "primary"); swimiop_status_update(floppy_count, ds); fs->state = idle; + fs->drive_num = i + 1; init_timer(&fs->timeout); floppy_count++; @@ -214,6 +232,7 @@ { req->sent = 0; req->complete = 0; + req->fs = NULL; req->done = NULL; } @@ -254,6 +273,26 @@ } /* + * Find the correct status slot for given hardware drive number + * + * This is only used for unsolicited messages + * + */ + +int swimiop_find_slot(int drive_num) +{ + struct floppy_state *fs; + int i; + + for (i = 0 ; i < MAX_FLOPPIES ; i++) { + fs = &floppy_states[i]; + if(fs->drive_num == drive_num) + return i; + } + return -1; +} + +/* * Receive a SWIM message from the IOP. * * This will be called in two cases: @@ -267,20 +306,32 @@ struct swim_iop_req *req; struct swimmsg_status *sm; struct swim_drvstatus *ds; + void (*done)(struct swim_iop_req *); + int drive_slot; req = current_req; switch(msg->status) { case IOP_MSGSTATUS_COMPLETE: + done = req->done; memcpy(&req->command[0], &msg->reply[0], sizeof(req->command)); req->complete = 1; - if (req->done) (*req->done)(req); + if (done) done(req); current_req = NULL; break; case IOP_MSGSTATUS_UNSOL: sm = (struct swimmsg_status *) &msg->message[0]; ds = &sm->status; - swimiop_status_update(sm->drive_num, ds); + drive_slot = swimiop_find_slot(sm->drive_num); + if(drive_slot >= 0) { + printk(KERN_ERR "SWIM_IOP: unit %d changed.\n", + drive_slot); + swimiop_status_update(drive_slot, ds); + } else { + printk("SWIM-IOP: Bad message from drive %d\n", + sm->drive_num); + } + memcpy(&msg->reply[0], &msg->message[0], IOP_MSG_LEN); iop_complete_message(msg); break; } @@ -347,7 +398,7 @@ schedule_timeout(1); } release_drive(fs); - return cmd->error; + return cmd->error ? -ENXIO : 0; } static ssize_t floppy_read(struct file *filp, char *buf,