diff options
author | dfr <dfr@FreeBSD.org> | 1998-09-26 14:49:26 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-09-26 14:49:26 +0000 |
commit | 94374025286df1d9b5cb9edb06c4d7aa88bc0270 (patch) | |
tree | eec2e7a5d3f742d1c11b1717b1ee96e1010cec51 /sys | |
parent | fb8743cea19e297125314ef4be80b455cb6e0739 (diff) | |
download | FreeBSD-src-94374025286df1d9b5cb9edb06c4d7aa88bc0270.zip FreeBSD-src-94374025286df1d9b5cb9edb06c4d7aa88bc0270.tar.gz |
Update SimOS scsi driver to use CAM.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/alpha/conf/SIMOS | 11 | ||||
-rw-r--r-- | sys/pci/simos.c | 305 |
2 files changed, 173 insertions, 143 deletions
diff --git a/sys/alpha/conf/SIMOS b/sys/alpha/conf/SIMOS index 4525c83..528506c 100644 --- a/sys/alpha/conf/SIMOS +++ b/sys/alpha/conf/SIMOS @@ -11,18 +11,15 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: SIMOS,v 1.1 1998/06/10 10:54:02 dfr Exp $ +# $Id: SIMOS,v 1.2 1998/06/28 00:48:48 dfr Exp $ machine "alpha" cpu "EV5" ident GENERIC maxusers 10 -options __FreeBSD__=3 #XXX hack city - options "DEC_KN8AE" options SIMOS -#options MATH_EMULATE #Support for x87 emulation options INET #InterNETworking options FFS #Berkeley Fast Filesystem options NFS #Network Filesystem @@ -33,11 +30,11 @@ options FFS_ROOT #FFS usable as root device [keep this!] options NFS_ROOT #NFS usable as root device options PROCFS #Process filesystem options "COMPAT_43" #Compatible with BSD 4.3 [KEEP THIS!] -options SCSI_DELAY=15 #Be pessimistic about Joe SCSI device +options SCSI_DELAY=100 #Be pessimistic about Joe SCSI device options UCONSOLE #Allow users to grab the console options FAILSAFE #Be conservative -config kernel root on sd0 +config kernel root on da0 controller pci0 controller tlsb0 @@ -49,7 +46,7 @@ controller simos0 controller scbus0 -device sd0 +device da0 device od0 #See LINT for possible `od' options. diff --git a/sys/pci/simos.c b/sys/pci/simos.c index 4e84edd..0be0397 100644 --- a/sys/pci/simos.c +++ b/sys/pci/simos.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: simos.c,v 1.1 1998/06/10 10:57:14 dfr Exp $ */ #include <sys/param.h> @@ -32,8 +32,14 @@ #include <sys/buf.h> #include <sys/proc.h> -#include <scsi/scsiconf.h> -#include <scsi/scsi_debug.h> +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_debug.h> + +#include <cam/scsi/scsi_all.h> +#include <cam/scsi/scsi_message.h> #include <machine/clock.h> #include <vm/vm.h> @@ -48,15 +54,16 @@ #include <machine/alpha_cpu.h> -#define MAX_SIZE (64*1024) - struct simos_softc { int sc_unit; - struct scsi_link sc_link; SimOS_SCSI* sc_regs; - int sc_busy; - struct scsi_xfer* sc_head; - struct scsi_xfer* sc_tail; + + /* + * SimOS only supports one pending command. + */ + struct cam_sim *sc_sim; + struct cam_path *sc_path; + struct ccb_scsiio *sc_pending; }; struct simos_softc* simosp[10]; @@ -65,6 +72,8 @@ static u_long simos_unit; static char *simos_probe __P((pcici_t tag, pcidi_t type)); static void simos_attach __P((pcici_t config_d, int unit)); +static void simos_action __P((struct cam_sim *sim, union ccb *ccb)); +static void simos_poll __P((struct cam_sim *sim)); struct pci_device simos_driver = { "simos", @@ -75,29 +84,6 @@ struct pci_device simos_driver = { }; DATA_SET (pcidevice_set, simos_driver); -static int32_t simos_start(struct scsi_xfer * xp); -static void simos_min_phys (struct buf *bp); -static u_int32_t simos_info(int unit); - -static struct scsi_adapter simos_switch = -{ - simos_start, - simos_min_phys, - 0, - 0, - simos_info, - "simos" -}; - -static struct scsi_device simos_dev = -{ - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ - "simos", -}; - static char * simos_probe(pcici_t tag, pcidi_t type) { @@ -114,7 +100,7 @@ static void simos_attach(pcici_t config_id, int unit) { struct simos_softc* sc; - struct scsibus_data* scbus; + struct cam_devq *devq; sc = malloc(sizeof(struct simos_softc), M_DEVBUF, M_WAITOK); simosp[unit] = sc; @@ -122,69 +108,98 @@ simos_attach(pcici_t config_id, int unit) sc->sc_unit = unit; sc->sc_regs = (SimOS_SCSI*) SIMOS_SCSI_ADDR; - sc->sc_busy = 0; - sc->sc_head = 0; - sc->sc_tail = 0; - - sc->sc_link.adapter_unit = unit; - sc->sc_link.adapter_softc = sc; - sc->sc_link.adapter_targ = SIMOS_SCSI_MAXTARG-1; - sc->sc_link.fordriver = 0; - sc->sc_link.adapter = &simos_switch; - sc->sc_link.device = &simos_dev; - sc->sc_link.flags = 0; - - scbus = scsi_alloc_bus(); - scbus->adapter_link = &sc->sc_link; - scbus->maxtarg = 1; - scbus->maxlun = 0; - scsi_attachdevs(scbus); - scbus = 0; -} + sc->sc_pending = 0; -static void -simos_enqueue(struct simos_softc* sc, struct scsi_xfer* xp) -{ - if (sc->sc_tail) { - sc->sc_tail->next = xp; - } else { - sc->sc_head = sc->sc_tail = xp; + devq = cam_simq_alloc(/*maxopenings*/1); + if (devq == NULL) + return; + + sc->sc_sim = cam_sim_alloc(simos_action, simos_poll, "simos", sc, unit, + /*untagged*/1, /*tagged*/0, devq); + if (sc->sc_sim == NULL) { + cam_simq_free(devq); + return; } - xp->next = 0; + + if (xpt_bus_register(sc->sc_sim, /*bus*/0) != CAM_SUCCESS) { + cam_sim_free(sc->sc_sim, /*free_devq*/TRUE); + return; + } + + if (xpt_create_path(&sc->sc_path, /*periph*/NULL, + cam_sim_path(sc->sc_sim), CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_bus_deregister(cam_sim_path(sc->sc_sim)); + cam_sim_free(sc->sc_sim, /*free_devq*/TRUE); + return; + } + + alpha_register_pci_scsi(config_id->bus, config_id->slot, sc->sc_sim); + + return; } static void -simos_start_transfer(struct simos_softc* sc) +simos_start(struct simos_softc* sc, struct ccb_scsiio *csio) { - struct scsi_xfer* xp = sc->sc_head; + struct scsi_generic *cmd; + int cmdlen; + caddr_t data; + int datalen; + int s; u_int8_t* p; int i, count, target; vm_offset_t va; vm_size_t size; - if (sc->sc_busy || !xp) + cmd = (struct scsi_generic *) &csio->cdb_io.cdb_bytes; + cmdlen = csio->cdb_len; + data = csio->data_ptr; + datalen = csio->dxfer_len; + + /* + * Simos doesn't understand some commands + */ + if (cmd->opcode == START_STOP || cmd->opcode == PREVENT_ALLOW + || cmd->opcode == SYNCHRONIZE_CACHE) { + csio->ccb_h.status = CAM_REQ_CMP; + xpt_done((union ccb *) csio); return; + } - sc->sc_busy = TRUE; + if (sc->sc_pending) { + /* + * Don't think this can happen. + */ + printf("simos_start: can't start command while one is pending\n"); + csio->ccb_h.status = CAM_BUSY; + xpt_done((union ccb *) csio); + return; + } + + s = splcam(); + + csio->ccb_h.status |= CAM_SIM_QUEUED; + sc->sc_pending = csio; - target = xp->sc_link->target; + target = csio->ccb_h.target_id; /* * Copy the command into SimOS' buffer */ - p = (u_int8_t*) xp->cmd; - count = xp->cmdlen; + p = (u_int8_t*) cmd; + count = cmdlen; for (i = 0; i < count; i++) sc->sc_regs->cmd[i] = *p++; sc->sc_regs->length = count; sc->sc_regs->target = target; - sc->sc_regs->lun = xp->sc_link->lun; + sc->sc_regs->lun = csio->ccb_h.target_lun; /* * Setup the segment descriptors. */ - va = (vm_offset_t) xp->data; - size = xp->datalen; + va = (vm_offset_t) data; + size = datalen; i = 0; while (size > 0) { vm_size_t len = PAGE_SIZE - (va & PAGE_MASK); @@ -204,102 +219,120 @@ simos_start_transfer(struct simos_softc* sc) alpha_wmb(); sc->sc_regs->startIO = 1; alpha_wmb(); + + splx(s); } static void simos_done(struct simos_softc* sc) { - struct scsi_xfer* xp; - int done; - - if (!sc->sc_busy) - return; - - xp = sc->sc_head; + struct ccb_scsiio* csio = sc->sc_pending; + int s, done; /* * Spurious interrupt caused by my bogus interrupt broadcasting. */ - if (!sc->sc_regs->done[xp->sc_link->target]) - return; + if (!csio) + return; - sc->sc_head = xp->next; - if (!sc->sc_head) - sc->sc_tail = 0; + sc->sc_pending = 0; - sc->sc_busy = FALSE; + done = sc->sc_regs->done[csio->ccb_h.target_id]; + if (!done) + return; - done = sc->sc_regs->done[xp->sc_link->target]; - if (done >> 16) { - /* Error detected */ - xp->error = XS_TIMEOUT; - } - xp->flags |= ITSDONE; + s = splcam(); - sc->sc_regs->done[xp->sc_link->target] = 1; + if (done >> 16) + /* Error detected */ + csio->ccb_h.status = CAM_CMD_TIMEOUT; + else + csio->ccb_h.status = CAM_REQ_CMP; + + /* + * Ack the interrupt to clear it. + */ + sc->sc_regs->done[csio->ccb_h.target_id] = 1; alpha_wmb(); - if (!(xp->flags & SCSI_NOMASK)) - scsi_done(xp); + xpt_done((union ccb *) csio); - if (sc->sc_head) - simos_start_transfer(sc); + splx(s); } -static int32_t -simos_start(struct scsi_xfer * xp) +static void +simos_action(struct cam_sim *sim, union ccb *ccb) { - struct simos_softc* sc; - int flags = xp->flags; - int retval = 0; - int s; + struct simos_softc* sc = (struct simos_softc *)sim->softc; - sc = xp->sc_link->adapter_softc; + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + { + struct ccb_scsiio *csio; - /* - * Reset (chortle) the adapter. - */ - if (flags & SCSI_RESET) - return COMPLETE; + csio = &ccb->csio; + simos_start(sc, csio); + break; + } - /* - * Simos doesn't understand some commands - */ - if (xp->cmd->opcode == START_STOP || xp->cmd->opcode == PREVENT_ALLOW) - return COMPLETE; + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg; + u_int32_t size_mb; + u_int32_t secs_per_cylinder; - s = splbio(); - - simos_enqueue(sc, xp); - simos_start_transfer(sc); + ccg = &ccb->ccg; + size_mb = ccg->volume_size + / ((1024L * 1024L) / ccg->block_size); - if (flags & SCSI_NOMASK) { - /* - * Poll for result - */ - while (!sc->sc_regs->done[xp->sc_link->target]) - ; + ccg->heads = 64; + ccg->secs_per_track = 32; + + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } + + case XPT_RESET_BUS: + { + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } - simos_done(sc); - retval = COMPLETE; - } else - retval = SUCCESSFULLY_QUEUED; + case XPT_PATH_INQ: + { + struct ccb_pathinq *cpi = &ccb->cpi; - splx(s); + cpi->version_num = 1; /* XXX??? */ + cpi->max_target = 2; + cpi->max_lun = 0; + cpi->initiator_id = 7; + cpi->bus_id = sim->bus_id; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "SimOS", HBA_IDLEN); + strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN); + cpi->unit_number = sim->unit_number; + + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } - return retval; + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } } static void -simos_min_phys (struct buf *bp) -{ - if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; -} - -static u_int32_t -simos_info(int unit) -{ - return 1; +simos_poll(struct cam_sim *sim) +{ + simos_done(cam_sim_softc(sim)); } void |