1 /* $NetBSD: hdc9224.c,v 1.49 2009/10/26 19:16:58 cegger Exp $ */
3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
6 * This code is derived from software contributed to Ludd by Bertram Barth.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed at Ludd, University of
19 * Lule}, Sweden and its contributors.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * with much help from (in alphabetical order):
42 * Rewritten by Ragge 25 Jun 2000. New features:
43 * - Uses interrupts instead of polling to signal ready.
44 * - Can cooperate with the SCSI routines WRT. the DMA area.
47 * - Floppy support missing.
48 * - Bad block forwarding missing.
49 * - Statistics collection.
53 #include <sys/cdefs.h>
54 __KERNEL_RCSID(0, "$NetBSD: hdc9224.c,v 1.49 2009/10/26 19:16:58 cegger Exp $");
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
62 #include <sys/ioctl.h>
66 #include <sys/device.h>
67 #include <sys/disklabel.h>
69 #include <sys/syslog.h>
70 #include <sys/reboot.h>
72 #include <uvm/uvm_extern.h>
74 #include <ufs/ufs/dinode.h> /* For BBSIZE */
75 #include <ufs/ffs/fs.h>
77 #include <machine/pte.h>
78 #include <machine/sid.h>
79 #include <machine/cpu.h>
80 #include <machine/uvax.h>
81 #include <machine/ka410.h>
82 #include <machine/vsbus.h>
83 #include <machine/rpb.h>
84 #include <machine/scb.h>
86 #include <dev/mscp/mscp.h> /* For DEC disk encoding */
88 #include <vax/vsa/hdc9224.h>
95 * on-disk geometry block
97 #define _aP __attribute__ ((packed)) /* force byte-alignment */
99 char mbz
[10]; /* 10 bytes of zero */
100 long xbn_count _aP
; /* number of XBNs */
101 long dbn_count _aP
; /* number of DBNs */
102 long lbn_count _aP
; /* number of LBNs (Logical-Block-Numbers) */
103 long rbn_count _aP
; /* number of RBNs (Replacement-Block-Numbers) */
104 short nspt
; /* number of sectors per track */
105 short ntracks
; /* number of tracks */
106 short ncylinders
; /* number of cylinders */
107 short precomp
; /* first cylinder for write precompensation */
108 short reduced
; /* first cylinder for reduced write current */
109 short seek_rate
; /* seek rate or zero for buffered seeks */
110 short crc_eec
; /* 0 if CRC, 1 if ECC is being used */
111 short rct
; /* "replacement control table" (RCT) */
112 short rct_ncopies
; /* number of copies of the RCT */
113 long media_id _aP
; /* media identifier */
114 short interleave
; /* sector-to-sector interleave */
115 short headskew
; /* head-to-head skew */
116 short cylskew
; /* cylinder-to-cylinder skew */
117 short gap0_size
; /* size of GAP 0 in the MFM format */
118 short gap1_size
; /* size of GAP 1 in the MFM format */
119 short gap2_size
; /* size of GAP 2 in the MFM format */
120 short gap3_size
; /* size of GAP 3 in the MFM format */
121 short sync_value
; /* sync value used when formatting */
122 char reserved
[32]; /* reserved for use by the RQDX formatter */
123 short serial_number
; /* serial number */
124 #if 0 /* we don't need these 412 useless bytes ... */
125 char fill
[412-2]; /* Filler bytes to the end of the block */
126 short checksum
; /* checksum over the XBN */
134 device_t sc_dev
; /* must be here! (pseudo-OOP:) */
135 struct hdcsoftc
*sc_hdc
;
136 struct disk sc_disk
; /* disklabel etc. */
137 struct rdgeom sc_xbn
; /* on-disk geometry information */
138 int sc_drive
; /* physical unit number */
142 device_t sc_dev
; /* must be here (pseudo-OOP:) */
143 struct evcnt sc_intrcnt
;
144 struct vsbus_dma sc_vd
;
145 vaddr_t sc_regs
; /* register addresses */
146 struct bufq_state
*sc_q
;
147 struct buf
*sc_active
;
148 struct hdc9224_UDCreg sc_creg
; /* (command) registers to be written */
149 struct hdc9224_UDCreg sc_sreg
; /* (status) registers being read */
150 void * sc_dmabase
; /* */
152 void *sc_bufaddr
; /* Current in-core address */
153 int sc_diskblk
; /* Current block on disk */
154 int sc_bytecnt
; /* How much left to transfer */
155 int sc_xfer
; /* Current transfer size */
157 volatile u_char sc_status
; /* last status from interrupt */
161 struct hdc_attach_args
{
166 * prototypes for (almost) all the internal routines
168 static int hdcmatch(device_t
, cfdata_t
, void *);
169 static void hdcattach(device_t
, device_t
, void *);
170 static int hdcprint(void *, const char *);
171 static int rdmatch(device_t
, cfdata_t
, void *);
172 static void rdattach(device_t
, device_t
, void *);
173 static void hdcintr(void *);
174 static int hdc_command(struct hdcsoftc
*, int);
175 static void rd_readgeom(struct hdcsoftc
*, struct rdsoftc
*);
177 static void hdc_printgeom( struct rdgeom
*);
179 static void hdc_writeregs(struct hdcsoftc
*);
180 static void hdcstart(struct hdcsoftc
*, struct buf
*);
181 static int hdc_rdselect(struct hdcsoftc
*, int);
182 static void rdmakelabel(struct disklabel
*, struct rdgeom
*);
183 static void hdc_writeregs(struct hdcsoftc
*);
184 static void hdc_readregs(struct hdcsoftc
*);
185 static void hdc_qstart(void *);
187 CFATTACH_DECL_NEW(hdc
, sizeof(struct hdcsoftc
),
188 hdcmatch
, hdcattach
, NULL
, NULL
);
190 CFATTACH_DECL_NEW(rd
, sizeof(struct rdsoftc
),
191 rdmatch
, rdattach
, NULL
, NULL
);
193 static dev_type_open(rdopen
);
194 static dev_type_close(rdclose
);
195 static dev_type_read(rdread
);
196 static dev_type_write(rdwrite
);
197 static dev_type_ioctl(rdioctl
);
198 static dev_type_strategy(rdstrategy
);
199 static dev_type_size(rdpsize
);
201 const struct bdevsw rd_bdevsw
= {
204 .d_strategy
= rdstrategy
,
211 const struct cdevsw rd_cdevsw
= {
221 .d_kqfilter
= nokqfilter
,
225 /* At least 0.7 uS between register accesses */
226 static int rd_dmasize
, inq
= 0;
227 static volatile int u
;
228 #define WAIT __asm("movl %0,%0;movl %0,%0;movl %0,%0; movl %0,%0" :: "m"(u))
230 #define HDC_WREG(x) *(volatile char *)(sc->sc_regs) = (x)
231 #define HDC_RREG *(volatile char *)(sc->sc_regs)
232 #define HDC_WCMD(x) *(volatile char *)(sc->sc_regs + 4) = (x)
233 #define HDC_RSTAT *(volatile char *)(sc->sc_regs + 4)
236 * new-config's hdcmatch() is similiar to old-config's hdcprobe(),
237 * thus we probe for the existence of the controller and reset it.
238 * NB: we can't initialize the controller yet, since space for hdcsoftc
239 * is not yet allocated. Thus we do this in hdcattach()...
242 hdcmatch(device_t parent
, cfdata_t cf
, void *aux
)
244 struct vsbus_attach_args
* const va
= aux
;
245 volatile char * const hdc_csr
= (volatile char *)va
->va_addr
;
248 u
= 8; /* !!! - GCC */
250 if (vax_boardtype
== VAX_BTYP_49
|| vax_boardtype
== VAX_BTYP_46
251 || vax_boardtype
== VAX_BTYP_48
|| vax_boardtype
== VAX_BTYP_53
)
254 hdc_csr
[4] = DKC_CMD_RESET
; /* reset chip */
255 for (i
= 0; i
< 1000; i
++) {
257 if (hdc_csr
[4] & DKC_ST_DONE
)
261 return 0; /* No response to reset */
263 hdc_csr
[4] = DKC_CMD_SETREGPTR
|UDC_TERM
;
265 hdc_csr
[0] = UDC_TC_CRCPRE
|UDC_TC_INTDONE
;
267 hdc_csr
[4] = DKC_CMD_DRDESELECT
; /* Should be harmless */
273 hdcprint(void *aux
, const char *name
)
275 struct hdc_attach_args
* const ha
= aux
;
278 aprint_normal ("RD?? at %s drive %d", name
, ha
->ha_drive
);
283 * hdc_attach() probes for all possible devices
286 hdcattach(device_t parent
, device_t self
, void *aux
)
288 struct vsbus_attach_args
* const va
= aux
;
289 struct hdcsoftc
* const sc
= device_private(self
);
290 struct hdc_attach_args ha
;
298 * Get interrupt vector, enable instrumentation.
300 scb_vecalloc(va
->va_cvec
, hdcintr
, sc
, SCB_ISTACK
, &sc
->sc_intrcnt
);
301 evcnt_attach_dynamic(&sc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
302 device_xname(self
), "intr");
304 sc
->sc_regs
= vax_map_physmem(va
->va_paddr
, 1);
305 sc
->sc_dmabase
= (void *)va
->va_dmaaddr
;
306 sc
->sc_dmasize
= va
->va_dmasize
;
307 sc
->sc_intbit
= va
->va_maskno
;
308 rd_dmasize
= min(MAXPHYS
, sc
->sc_dmasize
); /* Used in rd_minphys */
310 sc
->sc_vd
.vd_go
= hdc_qstart
;
311 sc
->sc_vd
.vd_arg
= sc
;
315 HDC_WCMD(DKC_CMD_RESET
);
318 if (status
!= (DKC_ST_DONE
|DKC_TC_SUCCESS
)) {
319 aprint_error_dev(self
, "RESET failed, status 0x%x\n", status
);
322 bufq_alloc(&sc
->sc_q
, "disksort", BUFQ_SORT_CYLINDER
);
325 * now probe for all possible hard drives
327 for (i
= 0; i
< 4; i
++) {
328 if (i
== 2) /* Floppy, needs special handling */
330 HDC_WCMD(DKC_CMD_DRSELECT
| i
);
334 if ((status
& DKC_ST_TERMCOD
) == DKC_TC_SUCCESS
)
335 config_found(self
, (void *)&ha
, hdcprint
);
340 * rdmatch() probes for the existence of a RD-type disk/floppy
343 rdmatch(device_t parent
, cfdata_t cf
, void *aux
)
345 struct hdc_attach_args
* const ha
= aux
;
347 if (cf
->cf_loc
[HDCCF_DRIVE
] != HDCCF_DRIVE_DEFAULT
&&
348 cf
->cf_loc
[HDCCF_DRIVE
] != ha
->ha_drive
)
351 if (ha
->ha_drive
== 2) /* Always floppy, not supported */
358 rdattach(device_t parent
, device_t self
, void *aux
)
360 struct hdcsoftc
* const sc
= device_private(parent
);
361 struct rdsoftc
* const rd
= device_private(self
);
362 struct hdc_attach_args
* const ha
= aux
;
363 struct disklabel
*dl
;
367 rd
->sc_drive
= ha
->ha_drive
;
370 * Initialize and attach the disk structure.
372 disk_init(&rd
->sc_disk
, device_xname(rd
->sc_dev
), NULL
);
373 disk_attach(&rd
->sc_disk
);
376 * if it's not a floppy then evaluate the on-disk geometry.
377 * if necessary correct the label...
380 disk_printtype(rd
->sc_drive
, rd
->sc_xbn
.media_id
);
381 dl
= rd
->sc_disk
.dk_label
;
382 rdmakelabel(dl
, &rd
->sc_xbn
);
383 msg
= readdisklabel(MAKEDISKDEV(cdevsw_lookup_major(&rd_cdevsw
),
384 device_unit(rd
->sc_dev
), RAW_PART
),
385 rdstrategy
, dl
, NULL
);
387 aprint_normal_dev(self
, "%s: size %u sectors",
388 msg
, dl
->d_secperunit
);
390 aprint_normal_dev(self
, "size %u sectors\n", dl
->d_secperunit
);
392 hdc_printgeom(&rd
->sc_xbn
);
399 struct hdcsoftc
* const sc
= arg
;
402 sc
->sc_status
= HDC_RSTAT
;
403 if (sc
->sc_active
== 0)
404 return; /* Complain? */
406 if ((sc
->sc_status
& (DKC_ST_INTPEND
|DKC_ST_DONE
)) !=
407 (DKC_ST_INTPEND
|DKC_ST_DONE
))
408 return; /* Why spurious ints sometimes??? */
412 if ((sc
->sc_status
& DKC_ST_TERMCOD
) != DKC_TC_SUCCESS
) {
414 u_char
*g
= (u_char
*)&sc
->sc_sreg
;
416 if (sc
->sc_retries
++ < 3) { /* Allow 3 retries */
420 aprint_error_dev(sc
->sc_dev
, "failed, status 0x%x\n",
423 for (i
= 0; i
< 10; i
++)
424 aprint_error("%i: %x\n", i
, g
[i
]);
426 bp
->b_resid
= bp
->b_bcount
;
432 if (bp
->b_flags
& B_READ
) {
433 vsbus_copytoproc(bp
->b_proc
, sc
->sc_dmabase
, sc
->sc_bufaddr
,
436 sc
->sc_diskblk
+= (sc
->sc_xfer
/DEV_BSIZE
);
437 sc
->sc_bytecnt
-= sc
->sc_xfer
;
438 sc
->sc_bufaddr
= (char *)sc
->sc_bufaddr
+ sc
->sc_xfer
;
440 if (sc
->sc_bytecnt
== 0) { /* Finished transfer */
451 rdstrategy(struct buf
*bp
)
455 struct disklabel
*lp
;
458 if ((rd
= device_lookup_private(&rd_cd
, DISKUNIT(bp
->b_dev
))) == NULL
) {
464 lp
= rd
->sc_disk
.dk_label
;
465 if ((bounds_check_with_label(&rd
->sc_disk
, bp
, 1)) <= 0)
468 if (bp
->b_bcount
== 0)
472 bp
->b_blkno
+ lp
->d_partitions
[DISKPART(bp
->b_dev
)].p_offset
;
473 bp
->b_cylinder
= bp
->b_rawblkno
/ lp
->d_secpercyl
;
476 bufq_put(sc
->sc_q
, bp
);
479 vsbus_dma_start(&sc
->sc_vd
);
488 hdc_qstart(void *arg
)
490 struct hdcsoftc
* const sc
= arg
;
495 if (bufq_peek(sc
->sc_q
)) {
496 vsbus_dma_start(&sc
->sc_vd
); /* More to go */
502 hdcstart(struct hdcsoftc
*sc
, struct buf
*ob
)
504 struct hdc9224_UDCreg
* const p
= &sc
->sc_creg
;
505 struct disklabel
*lp
;
508 int cn
, sn
, tn
, bn
, blks
;
512 return; /* Already doing something */
515 bp
= bufq_get(sc
->sc_q
);
517 return; /* Nothing to do */
518 sc
->sc_bufaddr
= bp
->b_data
;
519 sc
->sc_diskblk
= bp
->b_rawblkno
;
520 sc
->sc_bytecnt
= bp
->b_bcount
;
526 rd
= device_lookup_private(&rd_cd
, DISKUNIT(bp
->b_dev
));
527 hdc_rdselect(sc
, rd
->sc_drive
);
531 lp
= rd
->sc_disk
.dk_label
;
533 cn
= bn
/ lp
->d_secpercyl
;
534 sn
= bn
% lp
->d_secpercyl
;
535 tn
= sn
/ lp
->d_nsectors
;
536 sn
= sn
% lp
->d_nsectors
;
540 cn
++; /* first cylinder is reserved */
542 memset(p
, 0, sizeof(struct hdc9224_UDCreg
));
545 * Tricky thing: the controller do itself only increase the sector
546 * number, not the track or cylinder number. Therefore the driver
547 * is not allowed to have transfers that crosses track boundaries.
549 blks
= sc
->sc_bytecnt
/DEV_BSIZE
;
550 if ((sn
+ blks
) > lp
->d_nsectors
)
551 blks
= lp
->d_nsectors
- sn
;
554 p
->udc_dcyl
= cn
& 0xff;
555 p
->udc_dhead
= ((cn
>> 4) & 0x70) | tn
;
558 p
->udc_rtcnt
= UDC_RC_RTRYCNT
;
559 p
->udc_mode
= UDC_MD_HDD
;
560 p
->udc_term
= UDC_TC_CRCPRE
|UDC_TC_INTDONE
|UDC_TC_TDELDAT
|UDC_TC_TWRFLT
;
564 sc
->sc_xfer
= blks
* DEV_BSIZE
;
566 ch
= HDC_RSTAT
; /* Avoid pending interrupts */
568 vsbus_clrintr(sc
->sc_intbit
); /* Clear pending int's */
570 if (bp
->b_flags
& B_READ
) {
571 HDC_WCMD(DKC_CMD_READ_HDD
);
573 vsbus_copyfromproc(bp
->b_proc
, sc
->sc_bufaddr
, sc
->sc_dmabase
,
575 HDC_WCMD(DKC_CMD_WRITE_HDD
);
580 rd_readgeom(struct hdcsoftc
*sc
, struct rdsoftc
*rd
)
582 struct hdc9224_UDCreg
* const p
= &sc
->sc_creg
;
584 hdc_rdselect(sc
, rd
->sc_drive
); /* select drive right now */
586 memset(p
, 0, sizeof(*p
));
589 p
->udc_rtcnt
= UDC_RC_RTRYCNT
;
590 p
->udc_mode
= UDC_MD_HDD
;
591 p
->udc_term
= UDC_TC_CRCPRE
|UDC_TC_INTDONE
|UDC_TC_TDELDAT
|UDC_TC_TWPROT
;
594 HDC_WCMD(DKC_CMD_READ_HDD
|2);
595 while ((sc
->sc_status
& DKC_ST_INTPEND
) == 0)
597 memcpy(&rd
->sc_xbn
, sc
->sc_dmabase
, sizeof(struct rdgeom
));
602 * display the contents of the on-disk geometry structure
605 hdc_printgeom(struct rdgeom
*p
)
607 printf ("**DiskData** XBNs: %ld, DBNs: %ld, LBNs: %ld, RBNs: %ld\n",
608 p
->xbn_count
, p
->dbn_count
, p
->lbn_count
, p
->rbn_count
);
609 printf ("sec/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n",
610 p
->nspt
, p
->ntracks
, p
->ncylinders
, p
->precomp
, p
->reduced
);
611 printf ("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n",
612 p
->seek_rate
, p
->crc_eec
?"EEC":"CRC", p
->rct
, p
->rct_ncopies
);
613 printf ("media-ID: %lx, interleave: %d, headskew: %d, cylskew: %d\n",
614 p
->media_id
, p
->interleave
, p
->headskew
, p
->cylskew
);
615 printf ("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n",
616 p
->gap0_size
, p
->gap1_size
, p
->gap2_size
, p
->gap3_size
,
622 * Return the size of a partition, if known, or -1 if not.
627 struct rdsoftc
* const rd
= device_lookup_private(&rd_cd
, DISKUNIT(dev
));
628 const int part
= DISKPART(dev
);
630 if (rd
== NULL
|| part
>= rd
->sc_disk
.dk_label
->d_npartitions
)
633 return rd
->sc_disk
.dk_label
->d_partitions
[part
].p_size
*
634 (rd
->sc_disk
.dk_label
->d_secsize
/ DEV_BSIZE
);
641 rdopen(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
643 struct rdsoftc
* const rd
= device_lookup_private(&rd_cd
, DISKUNIT(dev
));
644 const int part
= DISKPART(dev
);
646 if (rd
== NULL
|| part
>= rd
->sc_disk
.dk_label
->d_npartitions
)
651 rd
->sc_disk
.dk_copenmask
|= (1 << part
);
654 rd
->sc_disk
.dk_bopenmask
|= (1 << part
);
657 rd
->sc_disk
.dk_openmask
=
658 rd
->sc_disk
.dk_copenmask
| rd
->sc_disk
.dk_bopenmask
;
667 rdclose(dev_t dev
, int flag
, int fmt
, struct lwp
*l
)
669 struct rdsoftc
* const rd
= device_lookup_private(&rd_cd
, DISKUNIT(dev
));
670 const int part
= DISKPART(dev
);
674 rd
->sc_disk
.dk_copenmask
&= ~(1 << part
);
677 rd
->sc_disk
.dk_bopenmask
&= ~(1 << part
);
680 rd
->sc_disk
.dk_openmask
=
681 rd
->sc_disk
.dk_copenmask
| rd
->sc_disk
.dk_bopenmask
;
690 rdioctl(dev_t dev
, u_long cmd
, void *addr
, int flag
, struct lwp
*l
)
692 struct rdsoftc
* const rd
= device_lookup_private(&rd_cd
, DISKUNIT(dev
));
693 struct disklabel
* const lp
= rd
->sc_disk
.dk_label
;
698 *(struct disklabel
*)addr
= *lp
;
702 ((struct partinfo
*)addr
)->disklab
= lp
;
703 ((struct partinfo
*)addr
)->part
=
704 &lp
->d_partitions
[DISKPART(dev
)];
709 if ((flag
& FWRITE
) == 0)
711 error
= (cmd
== DIOCSDINFO
?
712 setdisklabel(lp
, (struct disklabel
*)addr
, 0, 0) :
713 writedisklabel(dev
, rdstrategy
, lp
, 0));
717 memset(lp
, 0, sizeof(*lp
));
718 rdmakelabel(lp
, &rd
->sc_xbn
);
722 if ((flag
& FWRITE
) == 0)
736 rdread(dev_t dev
, struct uio
*uio
, int flag
)
738 return (physio (rdstrategy
, NULL
, dev
, B_READ
, minphys
, uio
));
745 rdwrite(dev_t dev
, struct uio
*uio
, int flag
)
747 return (physio (rdstrategy
, NULL
, dev
, B_WRITE
, minphys
, uio
));
751 * we have to wait 0.7 usec between two accesses to any of the
752 * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one
753 * instruction. Thus the loop-overhead will be enough...
756 hdc_readregs(struct hdcsoftc
*sc
)
761 HDC_WCMD(DKC_CMD_SETREGPTR
);
763 p
= (void*)&sc
->sc_sreg
;
764 for (i
=0; i
<10; i
++) {
765 *p
++ = HDC_RREG
; /* dkc_reg auto-increments */
771 hdc_writeregs(struct hdcsoftc
*sc
)
776 HDC_WCMD(DKC_CMD_SETREGPTR
);
777 p
= (void*)&sc
->sc_creg
;
778 for (i
=0; i
<10; i
++) {
779 HDC_WREG(*p
++); /* dkc_reg auto-increments */
785 * hdc_command() issues a command and polls the intreq-register
786 * to find when command has completed
789 hdc_command(struct hdcsoftc
*sc
, int cmd
)
791 hdc_writeregs(sc
); /* write the prepared registers */
798 hdc_rdselect(struct hdcsoftc
*sc
, int unit
)
800 struct hdc9224_UDCreg
* const p
= &sc
->sc_creg
;
804 * bring "creg" in some known-to-work state and
805 * select the drive with the DRIVE SELECT command.
807 memset(p
, 0, sizeof(*p
));
809 p
->udc_rtcnt
= UDC_RC_HDD_READ
;
810 p
->udc_mode
= UDC_MD_HDD
;
811 p
->udc_term
= UDC_TC_HDD
;
813 error
= hdc_command(sc
, DKC_CMD_DRSEL_HDD
| unit
);
819 rdmakelabel(struct disklabel
*dl
, struct rdgeom
*g
)
823 dl
->d_bbsize
= BBSIZE
;
824 dl
->d_sbsize
= SBLOCKSIZE
;
825 dl
->d_typename
[p
++] = MSCP_MID_CHAR(2, g
->media_id
);
826 dl
->d_typename
[p
++] = MSCP_MID_CHAR(1, g
->media_id
);
827 if (MSCP_MID_ECH(0, g
->media_id
))
828 dl
->d_typename
[p
++] = MSCP_MID_CHAR(0, g
->media_id
);
829 n
= MSCP_MID_NUM(g
->media_id
);
831 dl
->d_typename
[p
++] = '1';
835 dl
->d_typename
[p
++] = (n
/ 10) + '0';
838 dl
->d_typename
[p
++] = n
+ '0';
839 dl
->d_typename
[p
] = 0;
840 dl
->d_type
= DTYPE_MSCP
; /* XXX - what to use here??? */
842 dl
->d_secsize
= DEV_BSIZE
;
844 dl
->d_secperunit
= g
->lbn_count
;
845 dl
->d_nsectors
= g
->nspt
;
846 dl
->d_ntracks
= g
->ntracks
;
847 dl
->d_secpercyl
= dl
->d_nsectors
* dl
->d_ntracks
;
848 dl
->d_ncylinders
= dl
->d_secperunit
/ dl
->d_secpercyl
;
850 dl
->d_npartitions
= MAXPARTITIONS
;
851 dl
->d_partitions
[0].p_size
= dl
->d_partitions
[2].p_size
=
853 dl
->d_partitions
[0].p_offset
= dl
->d_partitions
[2].p_offset
= 0;
854 dl
->d_interleave
= dl
->d_headswitch
= 1;
855 dl
->d_magic
= dl
->d_magic2
= DISKMAGIC
;
856 dl
->d_checksum
= dkcksum(dl
);