diff options
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/gdt_common.c | 192 | ||||
-rw-r--r-- | sys/dev/ic/gdtvar.h | 23 |
2 files changed, 196 insertions, 19 deletions
diff --git a/sys/dev/ic/gdt_common.c b/sys/dev/ic/gdt_common.c index 9dea083808f..9de878584b2 100644 --- a/sys/dev/ic/gdt_common.c +++ b/sys/dev/ic/gdt_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gdt_common.c,v 1.32 2005/12/03 16:53:16 krw Exp $ */ +/* $OpenBSD: gdt_common.c,v 1.33 2006/05/07 20:34:08 marco Exp $ */ /* * Copyright (c) 1999, 2000, 2003 Niklas Hallqvist. All rights reserved. @@ -76,7 +76,12 @@ int gdt_internal_cmd(struct gdt_softc *, u_int8_t, u_int16_t, u_int32_t, u_int32_t, u_int32_t); #if NBIO > 0 int gdt_ioctl(struct device *, u_long, caddr_t); -#endif +int gdt_ioctl_inq(struct gdt_softc *, struct bioc_inq *); +int gdt_ioctl_vol(struct gdt_softc *, struct bioc_vol *); +int gdt_ioctl_disk(struct gdt_softc *, struct bioc_disk *); +int gdt_ioctl_alarm(struct gdt_softc *, struct bioc_alarm *); +int gdt_ioctl_setstate(struct gdt_softc *, struct bioc_setstate *); +#endif /* NBIO > 0 */ int gdt_raw_scsi_cmd(struct scsi_xfer *); int gdt_scsi_cmd(struct scsi_xfer *); void gdt_start_ccbs(struct gdt_softc *); @@ -123,10 +128,10 @@ gdt_attach(gdt) if (bus_dmamem_alloc(gdt->sc_dmat, GDT_SCRATCH_SZ, PAGE_SIZE, 0, &gdt->sc_scratch_seg, 1, &nsegs, BUS_DMA_NOWAIT)) - panic("%s: bus_dmamem_alloc failed", gdt->sc_dev.dv_xname); + panic("%s: bus_dmamem_alloc failed", DEVNAME(gdt)); if (bus_dmamem_map(gdt->sc_dmat, &gdt->sc_scratch_seg, 1, GDT_SCRATCH_SZ, &gdt->sc_scratch, BUS_DMA_NOWAIT)) - panic("%s: bus_dmamem_map failed", gdt->sc_dev.dv_xname); + panic("%s: bus_dmamem_map failed", DEVNAME(gdt)); gdt_clear_events(gdt); @@ -145,7 +150,7 @@ gdt_attach(gdt) &gdt->sc_ccbs[i].gc_dmamap_xfer); if (error) { printf("%s: cannot create ccb dmamap (%d)", - gdt->sc_dev.dv_xname, error); + DEVNAME(gdt), error); return (1); } (void)gdt_ccb_set_cmd(gdt->sc_ccbs + i, GDT_GCF_UNUSED); @@ -307,8 +312,48 @@ gdt_attach(gdt) /* Read more information */ if (gdt->sc_more_proc) { - /* XXX Not implemented yet */ - } + int bus; + /* physical drives, channel addresses */ + gdt_enc32(gdt->sc_scratch + GDT_IOC_VERSION, GDT_IOC_NEWEST); + gdt->sc_scratch[GDT_IOC_LIST_ENTRIES] = GDT_MAXBUS; + gdt->sc_scratch[GDT_IOC_FIRST_CHAN] = 0; + gdt->sc_scratch[GDT_IOC_LAST_CHAN] = GDT_MAXBUS - 1; + gdt_enc32(gdt->sc_scratch + GDT_IOC_LIST_OFFSET, GDT_IOC_HDR_SZ); + if (gdt_internal_cmd(gdt, GDT_CACHESERVICE, GDT_IOCTL, + GDT_IOCHAN_DESC, GDT_INVALID_CHANNEL, + GDT_IOC_HDR_SZ + GDT_RAWIOC_SZ)) { + GDT_DPRINTF(GDT_D_INFO, ("method 1\n")); + for (bus = 0; bus < gdt->sc_bus_cnt; bus++) { + gdt->sc_raw[bus].ra_address = + gdt_dec32(gdt->sc_scratch + + GDT_IOC_HDR_SZ + + GDT_IOC_SZ * bus + + GDT_IOC_ADDRESS); + gdt->sc_raw[bus].ra_local_no = + gdt_dec8(gdt->sc_scratch + + GDT_IOC_HDR_SZ + + GDT_IOC_SZ * bus + + GDT_IOC_LOCAL_NO); + GDT_DPRINTF(GDT_D_INFO, ( + "bus: %d address: %x local: %x\n", + bus, + gdt->sc_raw[bus].ra_address, + gdt->sc_raw[bus].ra_local_no)); + } + } else { + GDT_DPRINTF(GDT_D_INFO, ("method 2\n")); + for (bus = 0; bus < gdt->sc_bus_cnt; bus++) { + gdt->sc_raw[bus].ra_address = GDT_IO_CHANNEL; + gdt->sc_raw[bus].ra_local_no = bus; + GDT_DPRINTF(GDT_D_INFO, ( + "bus: %d address: %x local: %x\n", + bus, + gdt->sc_raw[bus].ra_address, + gdt->sc_raw[bus].ra_local_no)); + } + } + + } /* if (gdt->sc_more_proc) */ if (!gdt_internal_cmd(gdt, GDT_SCSIRAWSERVICE, GDT_INIT, 0, 0, 0)) { printf("raw service initialization error %d\n", @@ -377,18 +422,18 @@ gdt_attach(gdt) printf("dpmem %x %d-bus %d cache device%s\n", gdt->sc_dpmembase, gdt->sc_bus_cnt, cdev_cnt, cdev_cnt == 1 ? "" : "s"); printf("%s: ver %x, cache %s, strategy %d, writeback %s, blksz %d\n", - gdt->sc_dev.dv_xname, gdt->sc_cpar.cp_version, + DEVNAME(gdt), gdt->sc_cpar.cp_version, gdt->sc_cpar.cp_state ? "on" : "off", gdt->sc_cpar.cp_strategy, gdt->sc_cpar.cp_write_back ? "on" : "off", gdt->sc_cpar.cp_block_size); #if 1 - printf("%s: raw feat %x cache feat %x\n", gdt->sc_dev.dv_xname, + printf("%s: raw feat %x cache feat %x\n", DEVNAME(gdt), gdt->sc_raw_feat, gdt->sc_cache_feat); #endif #if NBIO > 0 if (bio_register(&gdt->sc_dev, gdt_ioctl) != 0) - panic("%s: controller registration failed", gdt->sc_dev.dv_xname); + panic("%s: controller registration failed", DEVNAME(gdt)); #endif gdt_cnt++; @@ -602,7 +647,7 @@ gdt_scsi_cmd(xs) gdt->sc_hdr[target].hd_size) { printf( "%s: out of bounds %u-%u >= %u\n", - gdt->sc_dev.dv_xname, blockno, + DEVNAME(gdt), blockno, blockcnt, gdt->sc_hdr[target].hd_size); /* @@ -641,7 +686,7 @@ gdt_scsi_cmd(xs) BUS_DMA_NOWAIT : BUS_DMA_WAITOK); if (error) { printf("%s: gdt_scsi_cmd: ", - gdt->sc_dev.dv_xname); + DEVNAME(gdt)); if (error == EFBIG) printf( "more than %d dma segs\n", @@ -670,7 +715,7 @@ gdt_scsi_cmd(xs) if (!gdt_wait(gdt, ccb, ccb->gc_timeout)) { GDT_UNLOCK_GDT(gdt, lock); printf("%s: command %d timed out\n", - gdt->sc_dev.dv_xname, + DEVNAME(gdt), ccb->gc_cmd_index); return (TRY_AGAIN_LATER); } @@ -801,7 +846,7 @@ gdt_exec_ccb(ccb) if (gdt->sc_cmd_cnt > 0 && gdt->sc_cmd_off + gdt->sc_cmd_len + GDT_DPMEM_COMMAND_OFFSET > gdt->sc_ic_all_size) { - printf("%s: DPMEM overflow\n", gdt->sc_dev.dv_xname); + printf("%s: DPMEM overflow\n", DEVNAME(gdt)); gdt_free_ccb(gdt, ccb); xs->error = XS_BUSY; #if 1 /* XXX */ @@ -915,10 +960,42 @@ int gdt_raw_scsi_cmd(xs) struct scsi_xfer *xs; { + struct scsi_link *link = xs->sc_link; + struct gdt_softc *gdt = link->adapter_softc; + struct gdt_ccb *ccb; + int s; + GDT_DPRINTF(GDT_D_CMD, ("gdt_raw_scsi_cmd ")); - /* XXX Not yet implemented */ + s = GDT_LOCK_GDT(gdt); + + if (xs->cmdlen > 12 /* XXX create #define */) { + GDT_DPRINTF(GDT_D_CMD, ("CDB too big %p ", xs)); + bzero(&xs->sense, sizeof(xs->sense)); + xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; + xs->sense.flags = SKEY_ILLEGAL_REQUEST; + xs->sense.add_sense_code = 0x20; /* illcmd, 0x24 illfield */ + xs->error = XS_SENSE; + scsi_done(xs); + GDT_UNLOCK_GDT(gdt, s); + return (COMPLETE); + } + + if ((ccb = gdt_get_ccb(gdt, xs->flags)) == NULL) { + GDT_DPRINTF(GDT_D_CMD, ("no ccb available for %p ", xs)); + xs->error = XS_DRIVER_STUFFUP; + scsi_done(xs); + GDT_UNLOCK_GDT(gdt, s); + return (COMPLETE); + } + xs->error = XS_DRIVER_STUFFUP; + xs->flags |= ITSDONE; + scsi_done(xs); + gdt_free_ccb(gdt, ccb); + + GDT_UNLOCK_GDT(gdt, s); + return (COMPLETE); } @@ -1033,7 +1110,7 @@ gdt_intr(arg) case GDT_SPEZINDEX: printf("%s: uninitialized or unknown service (%d %d)\n", - gdt->sc_dev.dv_xname, ctx.info, ctx.info2); + DEVNAME(gdt), ctx.info, ctx.info2); chain = 0; goto finish; } @@ -1145,7 +1222,7 @@ gdt_internal_cmd(gdt, service, opcode, arg1, arg2, arg3) ccb = gdt_get_ccb(gdt, SCSI_NOSLEEP); if (ccb == NULL) { printf("%s: no free command index found\n", - gdt->sc_dev.dv_xname); + DEVNAME(gdt)); return (0); } ccb->gc_service = service; @@ -1342,6 +1419,84 @@ gdt_watchdog(arg) #if NBIO > 0 int +gdt_ioctl(struct device *dev, u_long cmd, caddr_t addr) +{ + struct gdt_softc *sc = (struct gdt_softc *)dev; + int error = 0; + + GDT_DPRINTF(GDT_D_IOCTL, ("%s: ioctl ", DEVNAME(sc))); + + switch (cmd) { + case BIOCINQ: + GDT_DPRINTF(GDT_D_IOCTL, ("inq ")); + error = gdt_ioctl_inq(sc, (struct bioc_inq *)addr); + break; + + case BIOCVOL: + GDT_DPRINTF(GDT_D_IOCTL, ("vol ")); + error = gdt_ioctl_vol(sc, (struct bioc_vol *)addr); + break; + + case BIOCDISK: + GDT_DPRINTF(GDT_D_IOCTL, ("disk ")); + error = gdt_ioctl_disk(sc, (struct bioc_disk *)addr); + break; + + case BIOCALARM: + GDT_DPRINTF(GDT_D_IOCTL, ("alarm ")); + error = gdt_ioctl_alarm(sc, (struct bioc_alarm *)addr); + break; + + case BIOCSETSTATE: + GDT_DPRINTF(GDT_D_IOCTL, ("setstate ")); + error = gdt_ioctl_setstate(sc, (struct bioc_setstate *)addr); + break; + + default: + GDT_DPRINTF(GDT_D_IOCTL, (" invalid ioctl\n")); + error = EINVAL; + } + + return (error); +} + +int +gdt_ioctl_inq(struct gdt_softc *sc, struct bioc_inq *bi) +{ + bi->bi_novol = sc->sc_ndevs; + bi->bi_nodisk = 0; + + strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev)); + + return (0); +} + +int +gdt_ioctl_vol(struct gdt_softc *sc, struct bioc_vol *bv) +{ + return (1); /* XXX not yet */ +} + +int +gdt_ioctl_disk(struct gdt_softc *sc, struct bioc_disk *bd) +{ + return (1); /* XXX not yet */ +} + +int +gdt_ioctl_alarm(struct gdt_softc *sc, struct bioc_alarm *ba) +{ + return (1); /* XXX not yet */ +} + +int +gdt_ioctl_setstate(struct gdt_softc *sc, struct bioc_setstate *bs) +{ + return (1); /* XXX not yet */ +} + +#if 0 +int gdt_ioctl(dev, cmd, addr) struct device *dev; u_long cmd; @@ -1465,4 +1620,5 @@ gdt_ioctl(dev, cmd, addr) } return (error); } -#endif +#endif /* 0 */ +#endif /* NBIO > 0 */ diff --git a/sys/dev/ic/gdtvar.h b/sys/dev/ic/gdtvar.h index e36c15c6998..e801b7a443c 100644 --- a/sys/dev/ic/gdtvar.h +++ b/sys/dev/ic/gdtvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: gdtvar.h,v 1.10 2005/05/26 23:44:44 jason Exp $ */ +/* $OpenBSD: gdtvar.h,v 1.11 2006/05/07 20:34:09 marco Exp $ */ /* * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved. @@ -29,6 +29,7 @@ * from both ICP-Vortex and Öko.neT. I want to thank them for their support. */ +#define DEVNAME(s) ((s)->sc_dev.dv_xname) #define GDT_CMD_RESERVE 4 /* Internal driver cmd reserve. */ #define GDT_IOCTL_DUMMY _IOWR('B', 32, struct gdt_dummy) @@ -202,6 +203,7 @@ typedef struct gdt_statist { #ifdef _KERNEL /* Debugging */ +/* #define GDT_DEBUG GDT_D_IOCTL | GDT_D_INFO */ #ifdef GDT_DEBUG #define GDT_DPRINTF(mask, args) if (gdt_debug & (mask)) printf args #define GDT_D_INTR 0x01 @@ -209,6 +211,8 @@ typedef struct gdt_statist { #define GDT_D_CMD 0x04 #define GDT_D_QUEUE 0x08 #define GDT_D_IO 0x10 +#define GDT_D_IOCTL 0x20 +#define GDT_D_INFO 0x40 extern int gdt_debug; #else #define GDT_DPRINTF(mask, args) @@ -335,6 +339,15 @@ struct gdt_softc { } sc_hdr[GDT_MAX_HDRIVES]; struct { + u_int8_t ra_lock; /* chan locked? (hot plug */ + u_int8_t ra_phys_cnt; /* physical disk count */ + u_int8_t ra_local_no; /* local channel number */ + u_int8_t ra_io_cnt[GDT_MAXID]; /* current IO count */ + u_int32_t ra_address; /* channel address */ + u_int32_t ra_id_lis[GDT_MAXID]; /* IDs of phys disks */ + } sc_raw[GDT_MAXBUS]; /* SCSI channels */ + + struct { u_int32_t cp_version; u_int16_t cp_state; u_int16_t cp_strategy; @@ -401,6 +414,7 @@ int gdt_intr(void *); /* These all require correctly aligned buffers */ static __inline__ void gdt_enc16(u_int8_t *, u_int16_t); static __inline__ void gdt_enc32(u_int8_t *, u_int32_t); +static __inline__ u_int8_t gdt_dec8(u_int8_t *); static __inline__ u_int16_t gdt_dec16(u_int8_t *); static __inline__ u_int32_t gdt_dec32(u_int8_t *); @@ -420,6 +434,13 @@ gdt_enc32(addr, value) *(u_int32_t *)addr = htole32(value); } +static __inline__ u_int8_t +gdt_dec8(addr) + u_int8_t *addr; +{ + return *addr; +} + static __inline__ u_int16_t gdt_dec16(addr) u_int8_t *addr; |