Pull up following revision(s) (requested by bouyer in ticket #517): sys/arch/emips/ebus/flash_ebus.c: revision 1.21 sys/arch/emips/ebus/ace_ebus.c: revision 1.21 Drop advertisement clause from my licensesdiff -r1.20 -r1.20.20.1 src/sys/arch/emips/ebus/ace_ebus.c
(martin)
--- src/sys/arch/emips/ebus/ace_ebus.c 2016/11/20 03:30:11 1.20
+++ src/sys/arch/emips/ebus/ace_ebus.c 2019/12/08 14:43:16 1.20.20.1
@@ -1,2458 +1,2453 @@ | @@ -1,2458 +1,2453 @@ | |||
1 | /* $NetBSD: ace_ebus.c,v 1.20 2016/11/20 03:30:11 pgoyette Exp $ */ | 1 | /* $NetBSD: ace_ebus.c,v 1.20.20.1 2019/12/08 14:43:16 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code was written by Alessandro Forin and Neil Pittman | 7 | * This code was written by Alessandro Forin and Neil Pittman | |
8 | * at Microsoft Research and contributed to The NetBSD Foundation | 8 | * at Microsoft Research and contributed to The NetBSD Foundation | |
9 | * by Microsoft Corporation. | 9 | * by Microsoft Corporation. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: ace_ebus.c,v 1.20 2016/11/20 03:30:11 pgoyette Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: ace_ebus.c,v 1.20.20.1 2019/12/08 14:43:16 martin Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/systm.h> | 37 | #include <sys/systm.h> | |
38 | #include <sys/kernel.h> | 38 | #include <sys/kernel.h> | |
39 | #include <sys/conf.h> | 39 | #include <sys/conf.h> | |
40 | #include <sys/file.h> | 40 | #include <sys/file.h> | |
41 | #include <sys/stat.h> | 41 | #include <sys/stat.h> | |
42 | #include <sys/ioctl.h> | 42 | #include <sys/ioctl.h> | |
43 | #include <sys/buf.h> | 43 | #include <sys/buf.h> | |
44 | #include <sys/bufq.h> | 44 | #include <sys/bufq.h> | |
45 | #include <sys/uio.h> | 45 | #include <sys/uio.h> | |
46 | #include <sys/malloc.h> | 46 | #include <sys/malloc.h> | |
47 | #include <sys/device.h> | 47 | #include <sys/device.h> | |
48 | #include <sys/disklabel.h> | 48 | #include <sys/disklabel.h> | |
49 | #include <sys/disk.h> | 49 | #include <sys/disk.h> | |
50 | #include <sys/syslog.h> | 50 | #include <sys/syslog.h> | |
51 | #include <sys/proc.h> | 51 | #include <sys/proc.h> | |
52 | #include <sys/vnode.h> | 52 | #include <sys/vnode.h> | |
53 | #include <sys/kthread.h> | 53 | #include <sys/kthread.h> | |
54 | #include <sys/lock.h> | 54 | #include <sys/lock.h> | |
55 | #include <sys/queue.h> | 55 | #include <sys/queue.h> | |
56 | 56 | |||
57 | #include <sys/rndsource.h> | 57 | #include <sys/rndsource.h> | |
58 | 58 | |||
59 | #include <machine/intr.h> | 59 | #include <machine/intr.h> | |
60 | #include <machine/bus.h> | 60 | #include <machine/bus.h> | |
61 | 61 | |||
62 | #include "locators.h" | 62 | #include "locators.h" | |
63 | #include <prop/proplib.h> | 63 | #include <prop/proplib.h> | |
64 | 64 | |||
65 | #include <emips/ebus/ebusvar.h> | 65 | #include <emips/ebus/ebusvar.h> | |
66 | #include <emips/emips/machdep.h> | 66 | #include <emips/emips/machdep.h> | |
67 | #include <machine/emipsreg.h> | 67 | #include <machine/emipsreg.h> | |
68 | 68 | |||
69 | /* Structure returned by the Identify command (see CFlash specs) | 69 | /* Structure returned by the Identify command (see CFlash specs) | |
70 | * NB: We only care for the first sector so that is what we define here. | 70 | * NB: We only care for the first sector so that is what we define here. | |
71 | * NB: Beware of mis-alignment for all 32bit things | 71 | * NB: Beware of mis-alignment for all 32bit things | |
72 | */ | 72 | */ | |
73 | typedef struct _CFLASH_IDENTIFY { | 73 | typedef struct _CFLASH_IDENTIFY { | |
74 | uint16_t Signature; /* Word 0 */ | 74 | uint16_t Signature; /* Word 0 */ | |
75 | #define CFLASH_SIGNATURE 0x848a | 75 | #define CFLASH_SIGNATURE 0x848a | |
76 | uint16_t DefaultNumberOfCylinders; /* Word 1 */ | 76 | uint16_t DefaultNumberOfCylinders; /* Word 1 */ | |
77 | uint16_t Reserved1; /* Word 2 */ | 77 | uint16_t Reserved1; /* Word 2 */ | |
78 | uint16_t DefaultNumberOfHeads; /* Word 3 */ | 78 | uint16_t DefaultNumberOfHeads; /* Word 3 */ | |
79 | uint16_t Obsolete1[2]; /* Word 4 */ | 79 | uint16_t Obsolete1[2]; /* Word 4 */ | |
80 | uint16_t DefaultSectorsPerTrack; /* Word 6 */ | 80 | uint16_t DefaultSectorsPerTrack; /* Word 6 */ | |
81 | uint16_t SectorsPerCard[2]; /* Word 7 */ | 81 | uint16_t SectorsPerCard[2]; /* Word 7 */ | |
82 | uint16_t Obsolete2; /* Word 9 */ | 82 | uint16_t Obsolete2; /* Word 9 */ | |
83 | uint8_t SerialNumber[20]; /* padded, right-justified Word 10 */ | 83 | uint8_t SerialNumber[20]; /* padded, right-justified Word 10 */ | |
84 | uint16_t Obsolete3[2]; /* Word 20 */ | 84 | uint16_t Obsolete3[2]; /* Word 20 */ | |
85 | uint16_t EccBytesInRWLong; /* Word 22 */ | 85 | uint16_t EccBytesInRWLong; /* Word 22 */ | |
86 | uint8_t FirmwareRevision[8]; /* Word 23 */ | 86 | uint8_t FirmwareRevision[8]; /* Word 23 */ | |
87 | uint8_t ModelNumber[40]; /* Word 27 */ | 87 | uint8_t ModelNumber[40]; /* Word 27 */ | |
88 | uint16_t SectorsInRWMultiple; /* Word 47 */ | 88 | uint16_t SectorsInRWMultiple; /* Word 47 */ | |
89 | uint16_t Reserved2; /* Word 48 */ | 89 | uint16_t Reserved2; /* Word 48 */ | |
90 | uint16_t Capabilities; /* Word 49 */ | 90 | uint16_t Capabilities; /* Word 49 */ | |
91 | uint16_t Reserved3; /* Word 50 */ | 91 | uint16_t Reserved3; /* Word 50 */ | |
92 | uint16_t PioMode; /* Word 51 */ | 92 | uint16_t PioMode; /* Word 51 */ | |
93 | uint16_t Obsolete4; /* Word 52 */ | 93 | uint16_t Obsolete4; /* Word 52 */ | |
94 | uint16_t FieldValidity; /* Word 53 */ | 94 | uint16_t FieldValidity; /* Word 53 */ | |
95 | uint16_t CurrentNumberOfCylinders; /* Word 54 */ | 95 | uint16_t CurrentNumberOfCylinders; /* Word 54 */ | |
96 | uint16_t CurrentNumberOfHeads; /* Word 55 */ | 96 | uint16_t CurrentNumberOfHeads; /* Word 55 */ | |
97 | uint16_t CurrentSectorsPerTrack; /* Word 56 */ | 97 | uint16_t CurrentSectorsPerTrack; /* Word 56 */ | |
98 | uint16_t CurrentCapacity[2]; /* Word 57 */ | 98 | uint16_t CurrentCapacity[2]; /* Word 57 */ | |
99 | uint16_t MultiSectorSettings; /* Word 59 */ | 99 | uint16_t MultiSectorSettings; /* Word 59 */ | |
100 | uint16_t NumberOfAddressableSectors[2]; /* Word 60 */ | 100 | uint16_t NumberOfAddressableSectors[2]; /* Word 60 */ | |
101 | uint16_t Reserved4; /* Word 62 */ | 101 | uint16_t Reserved4; /* Word 62 */ | |
102 | uint16_t MultiWordDmaTransfer; /* Word 63 */ | 102 | uint16_t MultiWordDmaTransfer; /* Word 63 */ | |
103 | uint16_t AdvancedPioModes; /* Word 64 */ | 103 | uint16_t AdvancedPioModes; /* Word 64 */ | |
104 | uint16_t MinimumMultiWordDmaTiming; /* Word 65 */ | 104 | uint16_t MinimumMultiWordDmaTiming; /* Word 65 */ | |
105 | uint16_t RecommendedMultiWordDmaTiming; /* Word 66 */ | 105 | uint16_t RecommendedMultiWordDmaTiming; /* Word 66 */ | |
106 | uint16_t PioTimingNoFlowControl; /* Word 67 */ | 106 | uint16_t PioTimingNoFlowControl; /* Word 67 */ | |
107 | uint16_t PioTimingWithFlowControl; /* Word 68 */ | 107 | uint16_t PioTimingWithFlowControl; /* Word 68 */ | |
108 | uint16_t Reserved5[13]; /* Word 69 */ | 108 | uint16_t Reserved5[13]; /* Word 69 */ | |
109 | uint16_t FeaturesSupported[3]; /* Word 82 */ | 109 | uint16_t FeaturesSupported[3]; /* Word 82 */ | |
110 | uint16_t FeaturesEnabled[3]; /* Word 85 */ | 110 | uint16_t FeaturesEnabled[3]; /* Word 85 */ | |
111 | uint16_t UdmaMode; /* Word 88 */ | 111 | uint16_t UdmaMode; /* Word 88 */ | |
112 | uint16_t SecurityEraseTime; /* Word 89 */ | 112 | uint16_t SecurityEraseTime; /* Word 89 */ | |
113 | uint16_t EnhancedSecurityEraseTime; /* Word 90 */ | 113 | uint16_t EnhancedSecurityEraseTime; /* Word 90 */ | |
114 | uint16_t CurrentPowerManagementValue; /* Word 91 */ | 114 | uint16_t CurrentPowerManagementValue; /* Word 91 */ | |
115 | uint8_t Reserved6[72]; /* Word 92-127 */ | 115 | uint8_t Reserved6[72]; /* Word 92-127 */ | |
116 | uint8_t SecondHalf[256]; /* Word 128-255 */ | 116 | uint8_t SecondHalf[256]; /* Word 128-255 */ | |
117 | } CFLASH_IDENTIFY, *PCFLASH_IDENTIFY; | 117 | } CFLASH_IDENTIFY, *PCFLASH_IDENTIFY; | |
118 | 118 | |||
119 | #define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */ | 119 | #define SIZEOF_IDENTIFY CF_SECTOR_SIZE /* must be a sector multiple */ | |
120 | 120 | |||
121 | /* Instead of dragging in atavar.h.. */ | 121 | /* Instead of dragging in atavar.h.. */ | |
122 | /* | 122 | /* | |
123 | * Parameters/state needed by the controller to perform an ATA bio. | 123 | * Parameters/state needed by the controller to perform an ATA bio. | |
124 | */ | 124 | */ | |
125 | struct ace_bio { | 125 | struct ace_bio { | |
126 | volatile int flags;/* cmd flags */ | 126 | volatile int flags;/* cmd flags */ | |
127 | #define ATA_POLL 0x0002 /* poll for completion */ | 127 | #define ATA_POLL 0x0002 /* poll for completion */ | |
128 | #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */ | 128 | #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */ | |
129 | #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */ | 129 | #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */ | |
130 | #define ATA_CORR 0x0040 /* transfer had a corrected error */ | 130 | #define ATA_CORR 0x0040 /* transfer had a corrected error */ | |
131 | daddr_t blkno; /* block addr */ | 131 | daddr_t blkno; /* block addr */ | |
132 | daddr_t blkdone;/* number of blks transferred */ | 132 | daddr_t blkdone;/* number of blks transferred */ | |
133 | size_t nblks; /* number of blocks currently transferring */ | 133 | size_t nblks; /* number of blocks currently transferring */ | |
134 | size_t nbytes; /* number of bytes currently transferring */ | 134 | size_t nbytes; /* number of bytes currently transferring */ | |
135 | char *databuf;/* data buffer address */ | 135 | char *databuf;/* data buffer address */ | |
136 | volatile int error; | 136 | volatile int error; | |
137 | #define NOERROR 0 /* There was no error (r_error invalid), | 137 | #define NOERROR 0 /* There was no error (r_error invalid), | |
138 | else see acedone()*/ | 138 | else see acedone()*/ | |
139 | #define FAILED(er) (er != 0) | 139 | #define FAILED(er) (er != 0) | |
140 | #define EDOOFUS EIO | 140 | #define EDOOFUS EIO | |
141 | 141 | |||
142 | uint32_t r_error;/* copy of status register */ | 142 | uint32_t r_error;/* copy of status register */ | |
143 | #ifdef HAS_BAD144_HANDLING | 143 | #ifdef HAS_BAD144_HANDLING | |
144 | daddr_t badsect[127];/* 126 plus trailing -1 marker */ | 144 | daddr_t badsect[127];/* 126 plus trailing -1 marker */ | |
145 | #endif | 145 | #endif | |
146 | }; | 146 | }; | |
147 | /* End of atavar.h*/ | 147 | /* End of atavar.h*/ | |
148 | 148 | |||
149 | struct ace_softc { | 149 | struct ace_softc { | |
150 | /* General disk infos */ | 150 | /* General disk infos */ | |
151 | device_t sc_dev; | 151 | device_t sc_dev; | |
152 | 152 | |||
153 | struct disk sc_dk; | 153 | struct disk sc_dk; | |
154 | struct bufq_state *sc_q; | 154 | struct bufq_state *sc_q; | |
155 | struct callout sc_restart_ch; | 155 | struct callout sc_restart_ch; | |
156 | 156 | |||
157 | /* IDE disk soft states */ | 157 | /* IDE disk soft states */ | |
158 | struct buf *sc_bp; /* buf being transfered */ | 158 | struct buf *sc_bp; /* buf being transfered */ | |
159 | struct buf *active_xfer; /* buf handoff to thread */ | 159 | struct buf *active_xfer; /* buf handoff to thread */ | |
160 | /* current transfer data */ | 160 | /* current transfer data */ | |
161 | struct ace_bio sc_bio; /* current transfer */ | 161 | struct ace_bio sc_bio; /* current transfer */ | |
162 | 162 | |||
163 | struct proc *ch_thread; | 163 | struct proc *ch_thread; | |
164 | int ch_flags; | 164 | int ch_flags; | |
165 | #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */ | 165 | #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */ | |
166 | #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */ | 166 | #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */ | |
167 | #define ATACH_DISABLED 0x80 /* channel is disabled */ | 167 | #define ATACH_DISABLED 0x80 /* channel is disabled */ | |
168 | #define ATACH_TH_RUN 0x100 /* the kernel thread is working */ | 168 | #define ATACH_TH_RUN 0x100 /* the kernel thread is working */ | |
169 | #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ | 169 | #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ | |
170 | 170 | |||
171 | int openings; | 171 | int openings; | |
172 | int media_has_changed; | 172 | int media_has_changed; | |
173 | #define ACECE_MC 0x20 /* media changed */ | 173 | #define ACECE_MC 0x20 /* media changed */ | |
174 | #define ACECE_MCR 0x08 /* media change requested */ | 174 | #define ACECE_MCR 0x08 /* media change requested */ | |
175 | struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */ | 175 | struct _CFLASH_IDENTIFY sc_params;/* drive characteristics found */ | |
176 | 176 | |||
177 | int sc_flags; | 177 | int sc_flags; | |
178 | #define ACEF_WLABEL 0x004 /* label is writable */ | 178 | #define ACEF_WLABEL 0x004 /* label is writable */ | |
179 | #define ACEF_LABELLING 0x008 /* writing label */ | 179 | #define ACEF_LABELLING 0x008 /* writing label */ | |
180 | #define ACEF_LOADED 0x010 /* parameters loaded */ | 180 | #define ACEF_LOADED 0x010 /* parameters loaded */ | |
181 | #define ACEF_WAIT 0x020 /* waiting for resources */ | 181 | #define ACEF_WAIT 0x020 /* waiting for resources */ | |
182 | #define ACEF_KLABEL 0x080 /* retain label after 'full' close */ | 182 | #define ACEF_KLABEL 0x080 /* retain label after 'full' close */ | |
183 | 183 | |||
184 | uint64_t sc_capacity; | 184 | uint64_t sc_capacity; | |
185 | uint32_t sc_multi; /* max sectors per xfer */ | 185 | uint32_t sc_multi; /* max sectors per xfer */ | |
186 | 186 | |||
187 | struct _Sac *sc_dr; /* reg pointers */ | 187 | struct _Sac *sc_dr; /* reg pointers */ | |
188 | int hw_busy; | 188 | int hw_busy; | |
189 | int retries; /* number of xfer retry */ | 189 | int retries; /* number of xfer retry */ | |
190 | 190 | |||
191 | krndsource_t rnd_source; | 191 | krndsource_t rnd_source; | |
192 | }; | 192 | }; | |
193 | 193 | |||
194 | int ace_ebus_match(device_t, cfdata_t, void *); | 194 | int ace_ebus_match(device_t, cfdata_t, void *); | |
195 | void ace_ebus_attach(device_t, device_t, void *); | 195 | void ace_ebus_attach(device_t, device_t, void *); | |
196 | void aceattach(struct ace_softc *); | 196 | void aceattach(struct ace_softc *); | |
197 | int acedetach(device_t, int); | 197 | int acedetach(device_t, int); | |
198 | int aceactivate(device_t, enum devact); | 198 | int aceactivate(device_t, enum devact); | |
199 | 199 | |||
200 | void acedone(struct ace_softc *); | 200 | void acedone(struct ace_softc *); | |
201 | static void ace_set_geometry(struct ace_softc *ace); | 201 | static void ace_set_geometry(struct ace_softc *ace); | |
202 | 202 | |||
203 | CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc), | 203 | CFATTACH_DECL_NEW(ace_ebus, sizeof(struct ace_softc), | |
204 | ace_ebus_match, ace_ebus_attach, acedetach, aceactivate); | 204 | ace_ebus_match, ace_ebus_attach, acedetach, aceactivate); | |
205 | 205 | |||
206 | int ace_ebus_intr(void *cookie, void *f); | 206 | int ace_ebus_intr(void *cookie, void *f); | |
207 | 207 | |||
208 | static void sysace_thread(void *arg); | 208 | static void sysace_thread(void *arg); | |
209 | 209 | |||
210 | int | 210 | int | |
211 | ace_ebus_match(device_t parent, cfdata_t cf, void *aux) | 211 | ace_ebus_match(device_t parent, cfdata_t cf, void *aux) | |
212 | { | 212 | { | |
213 | struct ebus_attach_args *d = aux; | 213 | struct ebus_attach_args *d = aux; | |
214 | struct _Sac *sac = (struct _Sac *)d->ia_vaddr; | 214 | struct _Sac *sac = (struct _Sac *)d->ia_vaddr; | |
215 | 215 | |||
216 | if (strcmp("ace", d->ia_name) != 0) | 216 | if (strcmp("ace", d->ia_name) != 0) | |
217 | return 0; | 217 | return 0; | |
218 | if ((sac == NULL) || | 218 | if ((sac == NULL) || | |
219 | ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE)) | 219 | ((sac->Tag & SAC_TAG) != PMTTAG_SYSTEM_ACE)) | |
220 | return 0; | 220 | return 0; | |
221 | return 1; | 221 | return 1; | |
222 | } | 222 | } | |
223 | 223 | |||
224 | void | 224 | void | |
225 | ace_ebus_attach(device_t parent, device_t self, void *aux) | 225 | ace_ebus_attach(device_t parent, device_t self, void *aux) | |
226 | { | 226 | { | |
227 | struct ace_softc *ace = device_private(self); | 227 | struct ace_softc *ace = device_private(self); | |
228 | struct ebus_attach_args *ia = aux; | 228 | struct ebus_attach_args *ia = aux; | |
229 | int error; | 229 | int error; | |
230 | 230 | |||
231 | ace->sc_dev = self; | 231 | ace->sc_dev = self; | |
232 | 232 | |||
233 | /* | 233 | /* | |
234 | * It's on the baseboard, with a dedicated interrupt line. | 234 | * It's on the baseboard, with a dedicated interrupt line. | |
235 | */ | 235 | */ | |
236 | ace->sc_dr = (struct _Sac *)ia->ia_vaddr; | 236 | ace->sc_dr = (struct _Sac *)ia->ia_vaddr; | |
237 | #if DEBUG | 237 | #if DEBUG | |
238 | printf(" virt=%p", (void*)ace->sc_dr); | 238 | printf(" virt=%p", (void*)ace->sc_dr); | |
239 | #endif | 239 | #endif | |
240 | printf(" : System ACE\n"); | 240 | printf(" : System ACE\n"); | |
241 | 241 | |||
242 | ebus_intr_establish(parent, (void*)ia->ia_cookie, IPL_BIO, | 242 | ebus_intr_establish(parent, (void*)ia->ia_cookie, IPL_BIO, | |
243 | ace_ebus_intr, ace); | 243 | ace_ebus_intr, ace); | |
244 | 244 | |||
245 | config_pending_incr(self); | 245 | config_pending_incr(self); | |
246 | 246 | |||
247 | error = kthread_create(PRI_NONE, 0, NULL, sysace_thread, | 247 | error = kthread_create(PRI_NONE, 0, NULL, sysace_thread, | |
248 | ace, NULL, "%s", device_xname(ace->sc_dev)); | 248 | ace, NULL, "%s", device_xname(ace->sc_dev)); | |
249 | if (error) | 249 | if (error) | |
250 | aprint_error_dev(ace->sc_dev, "unable to create kernel " | 250 | aprint_error_dev(ace->sc_dev, "unable to create kernel " | |
251 | "thread: error %d\n", error); | 251 | "thread: error %d\n", error); | |
252 | } | 252 | } | |
253 | 253 | |||
254 | /* | 254 | /* | |
255 | * Sysace driver I(af) wrote for FreeBsd. | 255 | * Sysace driver I(af) wrote for FreeBsd. | |
256 | */ | 256 | */ | |
257 | #define CF_SECBITS 9 | 257 | #define CF_SECBITS 9 | |
258 | #define CF_SECTOR_SIZE (1 << CF_SECBITS) | 258 | #define CF_SECTOR_SIZE (1 << CF_SECBITS) | |
259 | 259 | |||
260 | static int sysace_attach(struct ace_softc *sc); | 260 | static int sysace_attach(struct ace_softc *sc); | |
261 | static int sysace_reset(struct ace_softc *sc); | 261 | static int sysace_reset(struct ace_softc *sc); | |
262 | static int sysace_identify(struct ace_softc *sc); | 262 | static int sysace_identify(struct ace_softc *sc); | |
263 | static int sysace_lock_registers(struct ace_softc *sc); | 263 | static int sysace_lock_registers(struct ace_softc *sc); | |
264 | static int sysace_unlock_registers(struct ace_softc *sc); | 264 | static int sysace_unlock_registers(struct ace_softc *sc); | |
265 | static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, | 265 | static int sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, | |
266 | uint32_t nSectors); | 266 | uint32_t nSectors); | |
267 | static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize); | 267 | static int sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize); | |
268 | static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector, | 268 | static int sysace_read_at (struct ace_softc *sc, daddr_t start_sector, | |
269 | char *buffer, size_t nblocks, size_t * pSizeRead); | 269 | char *buffer, size_t nblocks, size_t * pSizeRead); | |
270 | static int sysace_write_at(struct ace_softc *sc, daddr_t start_sector, | 270 | static int sysace_write_at(struct ace_softc *sc, daddr_t start_sector, | |
271 | char *buffer, size_t nblocks, size_t * pSizeWritten); | 271 | char *buffer, size_t nblocks, size_t * pSizeWritten); | |
272 | #ifdef USE_ACE_FOR_RECONFIG /* Old code, despised and replaced by ICAP */ | 272 | #ifdef USE_ACE_FOR_RECONFIG /* Old code, despised and replaced by ICAP */ | |
273 | static int sysace_send_config(struct ace_softc *sc, | 273 | static int sysace_send_config(struct ace_softc *sc, | |
274 | uint32_t *Data, unsigned int nBytes); | 274 | uint32_t *Data, unsigned int nBytes); | |
275 | #endif | 275 | #endif | |
276 | 276 | |||
277 | #define DEBUG_INTR 0x01 | 277 | #define DEBUG_INTR 0x01 | |
278 | #define DEBUG_XFERS 0x02 | 278 | #define DEBUG_XFERS 0x02 | |
279 | #define DEBUG_STATUS 0x04 | 279 | #define DEBUG_STATUS 0x04 | |
280 | #define DEBUG_FUNCS 0x08 | 280 | #define DEBUG_FUNCS 0x08 | |
281 | #define DEBUG_PROBE 0x10 | 281 | #define DEBUG_PROBE 0x10 | |
282 | #define DEBUG_WRITES 0x20 | 282 | #define DEBUG_WRITES 0x20 | |
283 | #define DEBUG_READS 0x40 | 283 | #define DEBUG_READS 0x40 | |
284 | #define DEBUG_ERRORS 0x80 | 284 | #define DEBUG_ERRORS 0x80 | |
285 | #ifdef DEBUG | 285 | #ifdef DEBUG | |
286 | int ace_debug = DEBUG_ERRORS /*|DEBUG_WRITES*/; | 286 | int ace_debug = DEBUG_ERRORS /*|DEBUG_WRITES*/; | |
287 | #define ACE_DEBUG(x) (ace_debug & (x)) | 287 | #define ACE_DEBUG(x) (ace_debug & (x)) | |
288 | #define DBGME(_lev_,_x_) if ((_lev_) & ace_debug) _x_ | 288 | #define DBGME(_lev_,_x_) if ((_lev_) & ace_debug) _x_ | |
289 | #else | 289 | #else | |
290 | #define ACE_DEBUG(x) (0) | 290 | #define ACE_DEBUG(x) (0) | |
291 | #define DBGME(_lev_,_x_) | 291 | #define DBGME(_lev_,_x_) | |
292 | #endif | 292 | #endif | |
293 | #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_) | 293 | #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_) | |
294 | 294 | |||
295 | static int | 295 | static int | |
296 | sysace_attach(struct ace_softc *sc) | 296 | sysace_attach(struct ace_softc *sc) | |
297 | { | 297 | { | |
298 | int error; | 298 | int error; | |
299 | 299 | |||
300 | DBGME(DEBUG_FUNCS, printf("Sysace::delayed_attach %p\n", sc)); | 300 | DBGME(DEBUG_FUNCS, printf("Sysace::delayed_attach %p\n", sc)); | |
301 | 301 | |||
302 | sc->media_has_changed = TRUE; | 302 | sc->media_has_changed = TRUE; | |
303 | sc->sc_capacity = 0; | 303 | sc->sc_capacity = 0; | |
304 | 304 | |||
305 | error = sysace_reset(sc); | 305 | error = sysace_reset(sc); | |
306 | if (error) { | 306 | if (error) { | |
307 | device_printf(sc->sc_dev, | 307 | device_printf(sc->sc_dev, | |
308 | "failed to reset, errno=%d\n", error); | 308 | "failed to reset, errno=%d\n", error); | |
309 | goto Out; | 309 | goto Out; | |
310 | } | 310 | } | |
311 | 311 | |||
312 | error = sysace_identify(sc); | 312 | error = sysace_identify(sc); | |
313 | if (error) { | 313 | if (error) { | |
314 | device_printf(sc->sc_dev, | 314 | device_printf(sc->sc_dev, | |
315 | "failed to identify card, errno=%d.\n", error); | 315 | "failed to identify card, errno=%d.\n", error); | |
316 | goto Out; | 316 | goto Out; | |
317 | } | 317 | } | |
318 | 318 | |||
319 | DBGME(DEBUG_PROBE, device_printf(sc->sc_dev, | 319 | DBGME(DEBUG_PROBE, device_printf(sc->sc_dev, | |
320 | "Card has %qx sectors.\n", sc->sc_capacity)); | 320 | "Card has %qx sectors.\n", sc->sc_capacity)); | |
321 | if (sc->sc_capacity == 0) { | 321 | if (sc->sc_capacity == 0) { | |
322 | device_printf(sc->sc_dev, "size 0, no card? Wont work.\n"); | 322 | device_printf(sc->sc_dev, "size 0, no card? Wont work.\n"); | |
323 | error = EDOOFUS; | 323 | error = EDOOFUS; | |
324 | goto Out; | 324 | goto Out; | |
325 | } | 325 | } | |
326 | 326 | |||
327 | sc->media_has_changed = FALSE; | 327 | sc->media_has_changed = FALSE; | |
328 | Out: | 328 | Out: | |
329 | return error; | 329 | return error; | |
330 | } | 330 | } | |
331 | 331 | |||
332 | static void | 332 | static void | |
333 | sysace_wedges(void *arg); | 333 | sysace_wedges(void *arg); | |
334 | extern int dkwedge_autodiscover; | 334 | extern int dkwedge_autodiscover; | |
335 | 335 | |||
336 | /* | 336 | /* | |
337 | * Aux temp thread to avoid deadlock when doing | 337 | * Aux temp thread to avoid deadlock when doing | |
338 | * the partitio.. ahem wedges thing. | 338 | * the partitio.. ahem wedges thing. | |
339 | */ | 339 | */ | |
340 | static void | 340 | static void | |
341 | sysace_wedges(void *arg) | 341 | sysace_wedges(void *arg) | |
342 | { | 342 | { | |
343 | struct ace_softc *sc = arg; | 343 | struct ace_softc *sc = arg; | |
344 | 344 | |||
345 | DBGME(DEBUG_STATUS, printf("Sysace::wedges started for %p\n", sc)); | 345 | DBGME(DEBUG_STATUS, printf("Sysace::wedges started for %p\n", sc)); | |
346 | 346 | |||
347 | /* Discover wedges on this disk. */ | 347 | /* Discover wedges on this disk. */ | |
348 | dkwedge_autodiscover = 1; | 348 | dkwedge_autodiscover = 1; | |
349 | dkwedge_discover(&sc->sc_dk); | 349 | dkwedge_discover(&sc->sc_dk); | |
350 | 350 | |||
351 | config_pending_decr(sc->sc_dev); | 351 | config_pending_decr(sc->sc_dev); | |
352 | 352 | |||
353 | DBGME(DEBUG_STATUS, printf("Sysace::thread done for %p\n", sc)); | 353 | DBGME(DEBUG_STATUS, printf("Sysace::thread done for %p\n", sc)); | |
354 | kthread_exit(0); | 354 | kthread_exit(0); | |
355 | } | 355 | } | |
356 | 356 | |||
357 | static void | 357 | static void | |
358 | sysace_thread(void *arg) | 358 | sysace_thread(void *arg) | |
359 | { | 359 | { | |
360 | struct ace_softc *sc = arg; | 360 | struct ace_softc *sc = arg; | |
361 | struct buf *bp; | 361 | struct buf *bp; | |
362 | int s, error; | 362 | int s, error; | |
363 | 363 | |||
364 | DBGME(DEBUG_STATUS, printf("Sysace::thread started for %p\n", sc)); | 364 | DBGME(DEBUG_STATUS, printf("Sysace::thread started for %p\n", sc)); | |
365 | 365 | |||
366 | s = splbio(); | 366 | s = splbio(); | |
367 | aceattach(sc); | 367 | aceattach(sc); | |
368 | splx(s); | 368 | splx(s); | |
369 | 369 | |||
370 | error = kthread_create(PRI_NONE, 0 /* MPSAFE??? */, NULL, | 370 | error = kthread_create(PRI_NONE, 0 /* MPSAFE??? */, NULL, | |
371 | sysace_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev)); | 371 | sysace_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev)); | |
372 | if (error) | 372 | if (error) | |
373 | aprint_error_dev(sc->sc_dev, "wedges: unable to create " | 373 | aprint_error_dev(sc->sc_dev, "wedges: unable to create " | |
374 | "kernel thread: error %d\n", error); | 374 | "kernel thread: error %d\n", error); | |
375 | 375 | |||
376 | DBGME(DEBUG_STATUS, | 376 | DBGME(DEBUG_STATUS, | |
377 | printf("Sysace::thread service active for %p\n", sc)); | 377 | printf("Sysace::thread service active for %p\n", sc)); | |
378 | 378 | |||
379 | s = splbio(); | 379 | s = splbio(); | |
380 | for (;;) { | 380 | for (;;) { | |
381 | /* Get next I/O request, wait if necessary */ | 381 | /* Get next I/O request, wait if necessary */ | |
382 | if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && | 382 | if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && | |
383 | (sc->active_xfer == NULL)) { | 383 | (sc->active_xfer == NULL)) { | |
384 | sc->ch_flags &= ~ATACH_TH_RUN; | 384 | sc->ch_flags &= ~ATACH_TH_RUN; | |
385 | (void) tsleep(&sc->ch_thread, PRIBIO, "aceth", 0); | 385 | (void) tsleep(&sc->ch_thread, PRIBIO, "aceth", 0); | |
386 | sc->ch_flags |= ATACH_TH_RUN; | 386 | sc->ch_flags |= ATACH_TH_RUN; | |
387 | } | 387 | } | |
388 | if (sc->ch_flags & ATACH_SHUTDOWN) | 388 | if (sc->ch_flags & ATACH_SHUTDOWN) | |
389 | break; | 389 | break; | |
390 | bp = sc->active_xfer; | 390 | bp = sc->active_xfer; | |
391 | sc->active_xfer = NULL; | 391 | sc->active_xfer = NULL; | |
392 | if (bp != NULL) { | 392 | if (bp != NULL) { | |
393 | size_t sz, bnow; | 393 | size_t sz, bnow; | |
394 | 394 | |||
395 | DBGME(DEBUG_XFERS, | 395 | DBGME(DEBUG_XFERS, | |
396 | printf("Sysace::task %p %p %x %p %qx %d (%zd)\n", | 396 | printf("Sysace::task %p %p %x %p %qx %d (%zd)\n", | |
397 | sc, bp, sc->sc_bio.flags, sc->sc_bio.databuf, | 397 | sc, bp, sc->sc_bio.flags, sc->sc_bio.databuf, | |
398 | sc->sc_bio.blkno, sc->sc_bio.nbytes, | 398 | sc->sc_bio.blkno, sc->sc_bio.nbytes, | |
399 | sc->sc_bio.nblks)); | 399 | sc->sc_bio.nblks)); | |
400 | 400 | |||
401 | sc->sc_bio.error = 0; | 401 | sc->sc_bio.error = 0; | |
402 | for (; sc->sc_bio.nblks > 0;) { | 402 | for (; sc->sc_bio.nblks > 0;) { | |
403 | 403 | |||
404 | bnow = sc->sc_bio.nblks; | 404 | bnow = sc->sc_bio.nblks; | |
405 | if (sc->sc_bio.flags & ATA_SINGLE) | 405 | if (sc->sc_bio.flags & ATA_SINGLE) | |
406 | bnow = 1; | 406 | bnow = 1; | |
407 | 407 | |||
408 | if (sc->sc_bio.flags & ATA_READ) { | 408 | if (sc->sc_bio.flags & ATA_READ) { | |
409 | sc->sc_bio.error = | 409 | sc->sc_bio.error = | |
410 | sysace_read_at(sc, | 410 | sysace_read_at(sc, | |
411 | sc->sc_bio.blkno, | 411 | sc->sc_bio.blkno, | |
412 | sc->sc_bio.databuf, bnow, &sz); | 412 | sc->sc_bio.databuf, bnow, &sz); | |
413 | } else { | 413 | } else { | |
414 | sc->sc_bio.error = | 414 | sc->sc_bio.error = | |
415 | sysace_write_at(sc, | 415 | sysace_write_at(sc, | |
416 | sc->sc_bio.blkno, | 416 | sc->sc_bio.blkno, | |
417 | sc->sc_bio.databuf, bnow, &sz); | 417 | sc->sc_bio.databuf, bnow, &sz); | |
418 | } | 418 | } | |
419 | 419 | |||
420 | if (FAILED(sc->sc_bio.error)) | 420 | if (FAILED(sc->sc_bio.error)) | |
421 | break; | 421 | break; | |
422 | 422 | |||
423 | sc->sc_bio.blkno += sz; /* in blocks */ | 423 | sc->sc_bio.blkno += sz; /* in blocks */ | |
424 | sc->sc_bio.nblks -= sz; | 424 | sc->sc_bio.nblks -= sz; | |
425 | sc->sc_bio.blkdone += sz; | 425 | sc->sc_bio.blkdone += sz; | |
426 | sz = sz << CF_SECBITS; /* in bytes */ | 426 | sz = sz << CF_SECBITS; /* in bytes */ | |
427 | sc->sc_bio.databuf += sz; | 427 | sc->sc_bio.databuf += sz; | |
428 | sc->sc_bio.nbytes -= sz; | 428 | sc->sc_bio.nbytes -= sz; | |
429 | } | 429 | } | |
430 | 430 | |||
431 | acedone(sc); | 431 | acedone(sc); | |
432 | } | 432 | } | |
433 | } | 433 | } | |
434 | 434 | |||
435 | splx(s); | 435 | splx(s); | |
436 | sc->ch_thread = NULL; | 436 | sc->ch_thread = NULL; | |
437 | wakeup(&sc->ch_flags); | 437 | wakeup(&sc->ch_flags); | |
438 | kthread_exit(0); | 438 | kthread_exit(0); | |
439 | } | 439 | } | |
440 | 440 | |||
441 | /* Worker routines | 441 | /* Worker routines | |
442 | */ | 442 | */ | |
443 | #if _DEBUG | 443 | #if _DEBUG | |
444 | typedef char *NAME; | 444 | typedef char *NAME; | |
445 | typedef struct _REGDESC { | 445 | typedef struct _REGDESC { | |
446 | NAME RegisterName; | 446 | NAME RegisterName; | |
447 | NAME BitNames[32]; | 447 | NAME BitNames[32]; | |
448 | } REGDESC, *PREGDESC; | 448 | } REGDESC, *PREGDESC; | |
449 | 449 | |||
450 | static void | 450 | static void | |
451 | SysacePrintRegister(const REGDESC *Desc, uint32_t Value) | 451 | SysacePrintRegister(const REGDESC *Desc, uint32_t Value) | |
452 | { | 452 | { | |
453 | int i; | 453 | int i; | |
454 | 454 | |||
455 | printf("\t%s %x =", Desc->RegisterName, Value); | 455 | printf("\t%s %x =", Desc->RegisterName, Value); | |
456 | for (i = 31; i >= 0; i--) { | 456 | for (i = 31; i >= 0; i--) { | |
457 | if (Value & (1 << i)) | 457 | if (Value & (1 << i)) | |
458 | printf(" %s", | 458 | printf(" %s", | |
459 | (Desc->BitNames[i]) ? Desc->BitNames[i] : "?"); | 459 | (Desc->BitNames[i]) ? Desc->BitNames[i] : "?"); | |
460 | } | 460 | } | |
461 | printf("\n"); | 461 | printf("\n"); | |
462 | } | 462 | } | |
463 | 463 | |||
464 | static uint32_t | 464 | static uint32_t | |
465 | SysaceDumpRegisters(struct _Sac *regs) | 465 | SysaceDumpRegisters(struct _Sac *regs) | |
466 | { | 466 | { | |
467 | const REGDESC Control_Names = { | 467 | const REGDESC Control_Names = { | |
468 | "Control", | 468 | "Control", | |
469 | { | 469 | { | |
470 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 470 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | |
471 | "RST", /* 0x00010000 */ | 471 | "RST", /* 0x00010000 */ | |
472 | "BUS8", /* 0x00020000 */ | 472 | "BUS8", /* 0x00020000 */ | |
473 | "BUS16", /* 0x00040000 */ | 473 | "BUS16", /* 0x00040000 */ | |
474 | "BUS32", /* 0x00080000 */ | 474 | "BUS32", /* 0x00080000 */ | |
475 | "IRQ", /* 0x00100000 */ | 475 | "IRQ", /* 0x00100000 */ | |
476 | "BRDY", /* 0x00200000 */ | 476 | "BRDY", /* 0x00200000 */ | |
477 | "IMSK0", /* 0x00400000 */ | 477 | "IMSK0", /* 0x00400000 */ | |
478 | "IMSK1", /* 0x00800000 */ | 478 | "IMSK1", /* 0x00800000 */ | |
479 | "TD0", /* 0x0f000000 */ | 479 | "TD0", /* 0x0f000000 */ | |
480 | "TD1", /* 0x0f000000 */ | 480 | "TD1", /* 0x0f000000 */ | |
481 | "TD2", /* 0x0f000000 */ | 481 | "TD2", /* 0x0f000000 */ | |
482 | "TD3", /* 0x0f000000 */ | 482 | "TD3", /* 0x0f000000 */ | |
483 | "BUFW8", /* 0x10000000 */ | 483 | "BUFW8", /* 0x10000000 */ | |
484 | "BUFW16", /* 0x20000000 */ | 484 | "BUFW16", /* 0x20000000 */ | |
485 | "BUFW32", /* 0x40000000 */ | 485 | "BUFW32", /* 0x40000000 */ | |
486 | "DEBUG" /* 0x80000000 */ | 486 | "DEBUG" /* 0x80000000 */ | |
487 | } | 487 | } | |
488 | }; | 488 | }; | |
489 | 489 | |||
490 | const REGDESC STATUS_Names = { | 490 | const REGDESC STATUS_Names = { | |
491 | "STATUS", | 491 | "STATUS", | |
492 | { | 492 | { | |
493 | "CFGLOCK", /* 0x00000001 */ | 493 | "CFGLOCK", /* 0x00000001 */ | |
494 | "MPULOCK", /* 0x00000002 */ | 494 | "MPULOCK", /* 0x00000002 */ | |
495 | "CFGERROR", /* 0x00000004 */ | 495 | "CFGERROR", /* 0x00000004 */ | |
496 | "CFCERROR", /* 0x00000008 */ | 496 | "CFCERROR", /* 0x00000008 */ | |
497 | "CFDETECT", /* 0x00000010 */ | 497 | "CFDETECT", /* 0x00000010 */ | |
498 | "DATABUFRDY", /* 0x00000020 */ | 498 | "DATABUFRDY", /* 0x00000020 */ | |
499 | "DATABUFWRITE", /* 0x00000040 */ | 499 | "DATABUFWRITE", /* 0x00000040 */ | |
500 | "CFGDONE", /* 0x00000080 */ | 500 | "CFGDONE", /* 0x00000080 */ | |
501 | "RDYFORCFCMD", /* 0x00000100 */ | 501 | "RDYFORCFCMD", /* 0x00000100 */ | |
502 | "CFGMODEPIN", /* 0x00000200 */ | 502 | "CFGMODEPIN", /* 0x00000200 */ | |
503 | 0,0,0, | 503 | 0,0,0, | |
504 | "CFGADDRPIN0", /* 0x0000e000 */ | 504 | "CFGADDRPIN0", /* 0x0000e000 */ | |
505 | "CFGADDRPIN1", /* 0x0000e000 */ | 505 | "CFGADDRPIN1", /* 0x0000e000 */ | |
506 | "CFGADDRPIN2", /* 0x0000e000 */ | 506 | "CFGADDRPIN2", /* 0x0000e000 */ | |
507 | 0, | 507 | 0, | |
508 | "CFBSY", /* 0x00020000 */ | 508 | "CFBSY", /* 0x00020000 */ | |
509 | "CFRDY", /* 0x00040000 */ | 509 | "CFRDY", /* 0x00040000 */ | |
510 | "CFDWF", /* 0x00080000 */ | 510 | "CFDWF", /* 0x00080000 */ | |
511 | "CFDSC", /* 0x00100000 */ | 511 | "CFDSC", /* 0x00100000 */ | |
512 | "CFDRQ", /* 0x00200000 */ | 512 | "CFDRQ", /* 0x00200000 */ | |
513 | "CFCORR", /* 0x00400000 */ | 513 | "CFCORR", /* 0x00400000 */ | |
514 | "CFERR", /* 0x00800000 */ | 514 | "CFERR", /* 0x00800000 */ | |
515 | 0, | 515 | 0, | |
516 | } | 516 | } | |
517 | }; | 517 | }; | |
518 | 518 | |||
519 | const REGDESC ERRORREG_Names = { | 519 | const REGDESC ERRORREG_Names = { | |
520 | "ERRORREG", | 520 | "ERRORREG", | |
521 | { | 521 | { | |
522 | "CARDRESETERR", /* 0x00000001 */ | 522 | "CARDRESETERR", /* 0x00000001 */ | |
523 | "CARDRDYERR", /* 0x00000002 */ | 523 | "CARDRDYERR", /* 0x00000002 */ | |
524 | "CARDREADERR", /* 0x00000004 */ | 524 | "CARDREADERR", /* 0x00000004 */ | |
525 | "CARDWRITEERR", /* 0x00000008 */ | 525 | "CARDWRITEERR", /* 0x00000008 */ | |
526 | "SECTORRDYERR", /* 0x00000010 */ | 526 | "SECTORRDYERR", /* 0x00000010 */ | |
527 | "CFGADDRERR", /* 0x00000020 */ | 527 | "CFGADDRERR", /* 0x00000020 */ | |
528 | "CFGFAILED", /* 0x00000040 */ | 528 | "CFGFAILED", /* 0x00000040 */ | |
529 | "CFGREADERR", /* 0x00000080 */ | 529 | "CFGREADERR", /* 0x00000080 */ | |
530 | "CFGINSTRERR", /* 0x00000100 */ | 530 | "CFGINSTRERR", /* 0x00000100 */ | |
531 | "CFGINITERR", /* 0x00000200 */ | 531 | "CFGINITERR", /* 0x00000200 */ | |
532 | 0, | 532 | 0, | |
533 | "CFBBK", /* 0x00000800 */ | 533 | "CFBBK", /* 0x00000800 */ | |
534 | "CFUNC", /* 0x00001000 */ | 534 | "CFUNC", /* 0x00001000 */ | |
535 | "CFIDNF", /* 0x00002000 */ | 535 | "CFIDNF", /* 0x00002000 */ | |
536 | "CFABORT", /* 0x00004000 */ | 536 | "CFABORT", /* 0x00004000 */ | |
537 | "CFAMNF", /* 0x00008000 */ | 537 | "CFAMNF", /* 0x00008000 */ | |
538 | 0, | 538 | 0, | |
539 | } | 539 | } | |
540 | }; | 540 | }; | |
541 | 541 | |||
542 | const NAME CommandNames[8] = { | 542 | const NAME CommandNames[8] = { | |
543 | "0", /* 0x0000 */ | 543 | "0", /* 0x0000 */ | |
544 | "RESETMEMCARD", /* 0x0100 */ | 544 | "RESETMEMCARD", /* 0x0100 */ | |
545 | "IDENTIFYMEMCARD", /* 0x0200 */ | 545 | "IDENTIFYMEMCARD", /* 0x0200 */ | |
546 | "READMEMCARDDATA", /* 0x0300 */ | 546 | "READMEMCARDDATA", /* 0x0300 */ | |
547 | "WRITEMEMCARDDATA", /* 0x0400 */ | 547 | "WRITEMEMCARDDATA", /* 0x0400 */ | |
548 | "5", /* 0x0500 */ | 548 | "5", /* 0x0500 */ | |
549 | "ABORT", /* 0x0600 */ | 549 | "ABORT", /* 0x0600 */ | |
550 | "7" /* 0x0700 */ | 550 | "7" /* 0x0700 */ | |
551 | }; | 551 | }; | |
552 | 552 | |||
553 | const REGDESC CONTROLREG_Names = { | 553 | const REGDESC CONTROLREG_Names = { | |
554 | "CONTROLREG", | 554 | "CONTROLREG", | |
555 | { | 555 | { | |
556 | "FORCELOCKREQ", /* 0x00000001 */ | 556 | "FORCELOCKREQ", /* 0x00000001 */ | |
557 | "LOCKREQ", /* 0x00000002 */ | 557 | "LOCKREQ", /* 0x00000002 */ | |
558 | "FORCECFGADDR", /* 0x00000004 */ | 558 | "FORCECFGADDR", /* 0x00000004 */ | |
559 | "FORCECFGMODE", /* 0x00000008 */ | 559 | "FORCECFGMODE", /* 0x00000008 */ | |
560 | "CFGMODE", /* 0x00000010 */ | 560 | "CFGMODE", /* 0x00000010 */ | |
561 | "CFGSTART", /* 0x00000020 */ | 561 | "CFGSTART", /* 0x00000020 */ | |
562 | "CFGSEL_MPU", /* 0x00000040 */ | 562 | "CFGSEL_MPU", /* 0x00000040 */ | |
563 | "CFGRESET", /* 0x00000080 */ | 563 | "CFGRESET", /* 0x00000080 */ | |
564 | "DATABUFRDYIRQ",/* 0x00000100 */ | 564 | "DATABUFRDYIRQ",/* 0x00000100 */ | |
565 | "ERRORIRQ", /* 0x00000200 */ | 565 | "ERRORIRQ", /* 0x00000200 */ | |
566 | "CFGDONEIRQ", /* 0x00000400 */ | 566 | "CFGDONEIRQ", /* 0x00000400 */ | |
567 | "RESETIRQ", /* 0x00000800 */ | 567 | "RESETIRQ", /* 0x00000800 */ | |
568 | "CFGPROG", /* 0x00001000 */ | 568 | "CFGPROG", /* 0x00001000 */ | |
569 | "CFGADDR_B0", /* 0x00002000 */ | 569 | "CFGADDR_B0", /* 0x00002000 */ | |
570 | "CFGADDR_B1", /* 0x00004000 */ | 570 | "CFGADDR_B1", /* 0x00004000 */ | |
571 | "CFGADDR_B2", /* 0x00008000 */ | 571 | "CFGADDR_B2", /* 0x00008000 */ | |
572 | 0, | 572 | 0, | |
573 | } | 573 | } | |
574 | }; | 574 | }; | |
575 | 575 | |||
576 | const REGDESC FATSTATREG_Names = { | 576 | const REGDESC FATSTATREG_Names = { | |
577 | "FATSTATREG", | 577 | "FATSTATREG", | |
578 | { | 578 | { | |
579 | "MBRVALID", /* 0x00000001 */ | 579 | "MBRVALID", /* 0x00000001 */ | |
580 | "PBRVALID", /* 0x00000002 */ | 580 | "PBRVALID", /* 0x00000002 */ | |
581 | "MBRFAT12", /* 0x00000004 */ | 581 | "MBRFAT12", /* 0x00000004 */ | |
582 | "PBRFAT12", /* 0x00000008 */ | 582 | "PBRFAT12", /* 0x00000008 */ | |
583 | "MBRFAT16", /* 0x00000010 */ | 583 | "MBRFAT16", /* 0x00000010 */ | |
584 | "PBRFAT16", /* 0x00000020 */ | 584 | "PBRFAT16", /* 0x00000020 */ | |
585 | "CALCFAT12", /* 0x00000040 */ | 585 | "CALCFAT12", /* 0x00000040 */ | |
586 | "CALCFAT16", /* 0x00000080 */ | 586 | "CALCFAT16", /* 0x00000080 */ | |
587 | 0, | 587 | 0, | |
588 | } | 588 | } | |
589 | }; | 589 | }; | |
590 | 590 | |||
591 | printf("Sysace@%p:\n", regs); | 591 | printf("Sysace@%p:\n", regs); | |
592 | printf("\tTag %x\n", regs->Tag); | 592 | printf("\tTag %x\n", regs->Tag); | |
593 | SysacePrintRegister(&Control_Names, regs->Control); | 593 | SysacePrintRegister(&Control_Names, regs->Control); | |
594 | printf("\tBUSMODEREG %x\n", regs->BUSMODEREG); | 594 | printf("\tBUSMODEREG %x\n", regs->BUSMODEREG); | |
595 | SysacePrintRegister(&STATUS_Names, regs->STATUS); | 595 | SysacePrintRegister(&STATUS_Names, regs->STATUS); | |
596 | SysacePrintRegister(&ERRORREG_Names, regs->ERRORREG); | 596 | SysacePrintRegister(&ERRORREG_Names, regs->ERRORREG); | |
597 | printf("\tCFGLBAREG %x\n", regs->CFGLBAREG); | 597 | printf("\tCFGLBAREG %x\n", regs->CFGLBAREG); | |
598 | printf("\tMPULBAREG %x\n", regs->MPULBAREG); | 598 | printf("\tMPULBAREG %x\n", regs->MPULBAREG); | |
599 | printf("\tVERSIONREG %x\n", regs->VERSIONREG); | 599 | printf("\tVERSIONREG %x\n", regs->VERSIONREG); | |
600 | printf("\tSECCNTCMDREG %x = %s cnt=%d\n", regs->SECCNTCMDREG, | 600 | printf("\tSECCNTCMDREG %x = %s cnt=%d\n", regs->SECCNTCMDREG, | |
601 | CommandNames[(regs->SECCNTCMDREG >> 8) & 7], | 601 | CommandNames[(regs->SECCNTCMDREG >> 8) & 7], | |
602 | regs->SECCNTCMDREG & SAC_SECCCNT); | 602 | regs->SECCNTCMDREG & SAC_SECCCNT); | |
603 | SysacePrintRegister(&CONTROLREG_Names, regs->CONTROLREG); | 603 | SysacePrintRegister(&CONTROLREG_Names, regs->CONTROLREG); | |
604 | SysacePrintRegister(&FATSTATREG_Names, regs->FATSTATREG); | 604 | SysacePrintRegister(&FATSTATREG_Names, regs->FATSTATREG); | |
605 | 605 | |||
606 | return 1; | 606 | return 1; | |
607 | } | 607 | } | |
608 | 608 | |||
609 | #else | 609 | #else | |
610 | #define SysaceDumpRegisters(_c_) | 610 | #define SysaceDumpRegisters(_c_) | |
611 | #endif | 611 | #endif | |
612 | 612 | |||
613 | /* | 613 | /* | |
614 | * Reset the device and the interface | 614 | * Reset the device and the interface | |
615 | */ | 615 | */ | |
616 | static int | 616 | static int | |
617 | sysace_reset(struct ace_softc *sc) | 617 | sysace_reset(struct ace_softc *sc) | |
618 | { | 618 | { | |
619 | struct _Sac *regs = sc->sc_dr; | 619 | struct _Sac *regs = sc->sc_dr; | |
620 | 620 | |||
621 | DBGME(DEBUG_FUNCS, printf("Sysace::Reset %p\n", sc)); | 621 | DBGME(DEBUG_FUNCS, printf("Sysace::Reset %p\n", sc)); | |
622 | 622 | |||
623 | /* 16bit etc etc */ | 623 | /* 16bit etc etc */ | |
624 | uint32_t BusMode, Control; | 624 | uint32_t BusMode, Control; | |
625 | 625 | |||
626 | /* reset our interface */ | 626 | /* reset our interface */ | |
627 | regs->Control = SAC_RST; | 627 | regs->Control = SAC_RST; | |
628 | DELAY(200); | 628 | DELAY(200); | |
629 | 629 | |||
630 | /* repeat on both byte lanes */ | 630 | /* repeat on both byte lanes */ | |
631 | regs->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8); | 631 | regs->BUSMODEREG = SAC_MODE16 | (SAC_MODE16 << 8); | |
632 | DELAY(1); | 632 | DELAY(1); | |
633 | 633 | |||
634 | /* check what our interface does and what the SysACE expects */ | 634 | /* check what our interface does and what the SysACE expects */ | |
635 | Control = regs->Control; | 635 | Control = regs->Control; | |
636 | BusMode = regs->BUSMODEREG; | 636 | BusMode = regs->BUSMODEREG; | |
637 | 637 | |||
638 | /* get them to agree */ | 638 | /* get them to agree */ | |
639 | if (BusMode & SAC_MODE16) { | 639 | if (BusMode & SAC_MODE16) { | |
640 | regs->Control = Control | SAC_BUS16; | 640 | regs->Control = Control | SAC_BUS16; | |
641 | regs->Control = regs->Control & ~SAC_BUS8; | 641 | regs->Control = regs->Control & ~SAC_BUS8; | |
642 | } else { | 642 | } else { | |
643 | regs->Control = Control | SAC_BUS8; | 643 | regs->Control = Control | SAC_BUS8; | |
644 | regs->Control = regs->Control & ~SAC_BUS16; | 644 | regs->Control = regs->Control & ~SAC_BUS16; | |
645 | } | 645 | } | |
646 | 646 | |||
647 | /* check that it worked */ | 647 | /* check that it worked */ | |
648 | BusMode = regs->BUSMODEREG; | 648 | BusMode = regs->BUSMODEREG; | |
649 | Control = regs->Control; | 649 | Control = regs->Control; | |
650 | 650 | |||
651 | if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) | 651 | if (((BusMode & SAC_MODE16) == 0) && ((Control & SAC_BUS8) == 0)) | |
652 | return EDOOFUS; | 652 | return EDOOFUS; | |
653 | if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) | 653 | if (((BusMode & SAC_MODE16) > 0) && ((Control & SAC_BUS16) == 0)) | |
654 | return EDOOFUS; | 654 | return EDOOFUS; | |
655 | 655 | |||
656 | /* interrupts off for now */ | 656 | /* interrupts off for now */ | |
657 | regs->Control &= ~SAC_INTMASK; | 657 | regs->Control &= ~SAC_INTMASK; | |
658 | #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ | SAC_ERRORIRQ /* | SAC_CFGDONEIRQ */) | 658 | #define SAC_INTERRUPTS (SAC_DATABUFRDYIRQ | SAC_ERRORIRQ /* | SAC_CFGDONEIRQ */) | |
659 | Control = regs->CONTROLREG; | 659 | Control = regs->CONTROLREG; | |
660 | Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE; | 660 | Control = (Control & ~SAC_INTERRUPTS) | SAC_RESETIRQ | SAC_FORCECFGMODE; | |
661 | regs->CONTROLREG = Control; | 661 | regs->CONTROLREG = Control; | |
662 | regs->CONTROLREG = Control & ~SAC_RESETIRQ; | 662 | regs->CONTROLREG = Control & ~SAC_RESETIRQ; | |
663 | 663 | |||
664 | /* no command */ | 664 | /* no command */ | |
665 | regs->MPULBAREG = 0; | 665 | regs->MPULBAREG = 0; | |
666 | 666 | |||
667 | return 0; | 667 | return 0; | |
668 | } | 668 | } | |
669 | 669 | |||
670 | /* | 670 | /* | |
671 | * Take control of the ACE datapath | 671 | * Take control of the ACE datapath | |
672 | */ | 672 | */ | |
673 | static int | 673 | static int | |
674 | sysace_lock_registers(struct ace_softc *sc) | 674 | sysace_lock_registers(struct ace_softc *sc) | |
675 | { | 675 | { | |
676 | uint32_t Status; | 676 | uint32_t Status; | |
677 | int i; | 677 | int i; | |
678 | 678 | |||
679 | DBGME(DEBUG_FUNCS, printf("Sysace::Lock %p\n", sc)); | 679 | DBGME(DEBUG_FUNCS, printf("Sysace::Lock %p\n", sc)); | |
680 | 680 | |||
681 | /* | 681 | /* | |
682 | * Locked already? | 682 | * Locked already? | |
683 | */ | 683 | */ | |
684 | Status = sc->sc_dr->STATUS; | 684 | Status = sc->sc_dr->STATUS; | |
685 | if (Status & SAC_MPULOCK) | 685 | if (Status & SAC_MPULOCK) | |
686 | return TRUE; | 686 | return TRUE; | |
687 | 687 | |||
688 | /* | 688 | /* | |
689 | * Request lock | 689 | * Request lock | |
690 | */ | 690 | */ | |
691 | sc->sc_dr->CONTROLREG |= SAC_LOCKREQ; | 691 | sc->sc_dr->CONTROLREG |= SAC_LOCKREQ; | |
692 | 692 | |||
693 | /* | 693 | /* | |
694 | * Spin a bit until we get it | 694 | * Spin a bit until we get it | |
695 | */ | 695 | */ | |
696 | for (i = 0; i < 200; i++) { | 696 | for (i = 0; i < 200; i++) { | |
697 | Status = sc->sc_dr->STATUS; | 697 | Status = sc->sc_dr->STATUS; | |
698 | if (Status & SAC_MPULOCK) | 698 | if (Status & SAC_MPULOCK) | |
699 | return TRUE; | 699 | return TRUE; | |
700 | DELAY(100); | 700 | DELAY(100); | |
701 | DBGME(DEBUG_FUNCS, | 701 | DBGME(DEBUG_FUNCS, | |
702 | printf("Sysace::Lock loops.. (st=%x)\n",Status)); | 702 | printf("Sysace::Lock loops.. (st=%x)\n",Status)); | |
703 | } | 703 | } | |
704 | 704 | |||
705 | /* | 705 | /* | |
706 | * oopsie! | 706 | * oopsie! | |
707 | */ | 707 | */ | |
708 | DBGME(DEBUG_ERRORS, printf("Sysace::Lock timeout (st=%x)\n",Status)); | 708 | DBGME(DEBUG_ERRORS, printf("Sysace::Lock timeout (st=%x)\n",Status)); | |
709 | SysaceDumpRegisters(sc->sc_dr); | 709 | SysaceDumpRegisters(sc->sc_dr); | |
710 | return FALSE; | 710 | return FALSE; | |
711 | } | 711 | } | |
712 | 712 | |||
713 | /* | 713 | /* | |
714 | * Release control of the ACE datapath | 714 | * Release control of the ACE datapath | |
715 | */ | 715 | */ | |
716 | static int | 716 | static int | |
717 | sysace_unlock_registers(struct ace_softc *sc) | 717 | sysace_unlock_registers(struct ace_softc *sc) | |
718 | { | 718 | { | |
719 | uint32_t Status; | 719 | uint32_t Status; | |
720 | int i; | 720 | int i; | |
721 | 721 | |||
722 | DBGME(DEBUG_FUNCS, printf("Sysace::Unlock %p\n", sc)); | 722 | DBGME(DEBUG_FUNCS, printf("Sysace::Unlock %p\n", sc)); | |
723 | 723 | |||
724 | /* | 724 | /* | |
725 | * Clear reset | 725 | * Clear reset | |
726 | */ | 726 | */ | |
727 | sc->sc_dr->CONTROLREG &= ~SAC_CFGRESET; | 727 | sc->sc_dr->CONTROLREG &= ~SAC_CFGRESET; | |
728 | 728 | |||
729 | /* | 729 | /* | |
730 | * Unlocked already? | 730 | * Unlocked already? | |
731 | */ | 731 | */ | |
732 | Status = sc->sc_dr->STATUS; | 732 | Status = sc->sc_dr->STATUS; | |
733 | if ((Status & SAC_MPULOCK) == 0) | 733 | if ((Status & SAC_MPULOCK) == 0) | |
734 | return TRUE; | 734 | return TRUE; | |
735 | 735 | |||
736 | /* | 736 | /* | |
737 | * Request unlock | 737 | * Request unlock | |
738 | */ | 738 | */ | |
739 | sc->sc_dr->CONTROLREG &= ~SAC_LOCKREQ; | 739 | sc->sc_dr->CONTROLREG &= ~SAC_LOCKREQ; | |
740 | 740 | |||
741 | /* | 741 | /* | |
742 | * Spin a bit until we get it | 742 | * Spin a bit until we get it | |
743 | */ | 743 | */ | |
744 | for (i = 0; i < 200; i++) { | 744 | for (i = 0; i < 200; i++) { | |
745 | Status = sc->sc_dr->STATUS; | 745 | Status = sc->sc_dr->STATUS; | |
746 | if ((Status & SAC_MPULOCK) == 0) | 746 | if ((Status & SAC_MPULOCK) == 0) | |
747 | return TRUE; | 747 | return TRUE; | |
748 | DELAY(100); | 748 | DELAY(100); | |
749 | DBGME(DEBUG_FUNCS, | 749 | DBGME(DEBUG_FUNCS, | |
750 | printf("Sysace::Unlock loops.. (st=%x)\n",Status)); | 750 | printf("Sysace::Unlock loops.. (st=%x)\n",Status)); | |
751 | } | 751 | } | |
752 | 752 | |||
753 | /* | 753 | /* | |
754 | * oopsie! | 754 | * oopsie! | |
755 | */ | 755 | */ | |
756 | DBGME(DEBUG_ERRORS, printf("Sysace::Unlock timeout (st=%x)\n",Status)); | 756 | DBGME(DEBUG_ERRORS, printf("Sysace::Unlock timeout (st=%x)\n",Status)); | |
757 | SysaceDumpRegisters(sc->sc_dr); | 757 | SysaceDumpRegisters(sc->sc_dr); | |
758 | return FALSE; | 758 | return FALSE; | |
759 | } | 759 | } | |
760 | 760 | |||
761 | /* | 761 | /* | |
762 | * Check if the ACE is waiting for a comamnd | 762 | * Check if the ACE is waiting for a comamnd | |
763 | */ | 763 | */ | |
764 | #define sysace_ready(_s_) ((_s_)->sc_dr->STATUS & SAC_RDYFORCFCMD) | 764 | #define sysace_ready(_s_) ((_s_)->sc_dr->STATUS & SAC_RDYFORCFCMD) | |
765 | 765 | |||
766 | /* | 766 | /* | |
767 | * Check if the ACE is executing a comamnd | 767 | * Check if the ACE is executing a comamnd | |
768 | */ | 768 | */ | |
769 | #define sysace_busy(_s_) ((_s_)->sc_dr->STATUS & SAC_CFBSY) | 769 | #define sysace_busy(_s_) ((_s_)->sc_dr->STATUS & SAC_CFBSY) | |
770 | 770 | |||
771 | /* | 771 | /* | |
772 | * Turn on interrupts from the ACE | 772 | * Turn on interrupts from the ACE | |
773 | */ | 773 | */ | |
774 | #define sysace_inton(_s_) { \ | 774 | #define sysace_inton(_s_) { \ | |
775 | (_s_)->sc_dr->CONTROLREG |= SAC_INTERRUPTS; \ | 775 | (_s_)->sc_dr->CONTROLREG |= SAC_INTERRUPTS; \ | |
776 | (_s_)->sc_dr->Control |= SAC_INTMASK; \ | 776 | (_s_)->sc_dr->Control |= SAC_INTMASK; \ | |
777 | } | 777 | } | |
778 | 778 | |||
779 | /* | 779 | /* | |
780 | * Turn off interrupts from the ACE | 780 | * Turn off interrupts from the ACE | |
781 | */ | 781 | */ | |
782 | #define sysace_intoff(_s_) { \ | 782 | #define sysace_intoff(_s_) { \ | |
783 | (_s_)->sc_dr->CONTROLREG &= ~SAC_INTERRUPTS; \ | 783 | (_s_)->sc_dr->CONTROLREG &= ~SAC_INTERRUPTS; \ | |
784 | (_s_)->sc_dr->Control &= ~SAC_INTMASK; \ | 784 | (_s_)->sc_dr->Control &= ~SAC_INTMASK; \ | |
785 | } | 785 | } | |
786 | 786 | |||
787 | /* | 787 | /* | |
788 | * Start a command on the ACE, such as read or identify. | 788 | * Start a command on the ACE, such as read or identify. | |
789 | */ | 789 | */ | |
790 | static int | 790 | static int | |
791 | sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, | 791 | sysace_start(struct ace_softc *sc, uint32_t Command, uint32_t Lba, | |
792 | uint32_t nSectors) | 792 | uint32_t nSectors) | |
793 | { | 793 | { | |
794 | 794 | |||
795 | /* | 795 | /* | |
796 | * Lock it if not already | 796 | * Lock it if not already | |
797 | */ | 797 | */ | |
798 | if (!sysace_lock_registers(sc)) { | 798 | if (!sysace_lock_registers(sc)) { | |
799 | /* printed already */ | 799 | /* printed already */ | |
800 | return ETIMEDOUT; | 800 | return ETIMEDOUT; | |
801 | } | 801 | } | |
802 | 802 | |||
803 | /* | 803 | /* | |
804 | * Is there a CF inserted | 804 | * Is there a CF inserted | |
805 | */ | 805 | */ | |
806 | if (!(sc->sc_dr->STATUS & SAC_CFDETECT)) { | 806 | if (!(sc->sc_dr->STATUS & SAC_CFDETECT)) { | |
807 | /* NB: Not a failure state */ | 807 | /* NB: Not a failure state */ | |
808 | DBGME(DEBUG_ERRORS, | 808 | DBGME(DEBUG_ERRORS, | |
809 | printf("Sysace:: no media (st=%x)\n", sc->sc_dr->STATUS)); | 809 | printf("Sysace:: no media (st=%x)\n", sc->sc_dr->STATUS)); | |
810 | if (sc->sc_capacity) { | 810 | if (sc->sc_capacity) { | |
811 | sc->media_has_changed = TRUE; | 811 | sc->media_has_changed = TRUE; | |
812 | sc->sc_capacity = 0; | 812 | sc->sc_capacity = 0; | |
813 | } | 813 | } | |
814 | return ENODEV; | 814 | return ENODEV; | |
815 | } | 815 | } | |
816 | 816 | |||
817 | /* | 817 | /* | |
818 | * Is it ready for a command | 818 | * Is it ready for a command | |
819 | */ | 819 | */ | |
820 | if (!sysace_ready(sc)) { | 820 | if (!sysace_ready(sc)) { | |
821 | DBGME(DEBUG_ERRORS, | 821 | DBGME(DEBUG_ERRORS, | |
822 | printf("Sysace:: not ready (st=%x)\n", sc->sc_dr->STATUS)); | 822 | printf("Sysace:: not ready (st=%x)\n", sc->sc_dr->STATUS)); | |
823 | SysaceDumpRegisters(sc->sc_dr); | 823 | SysaceDumpRegisters(sc->sc_dr); | |
824 | return EBUSY; | 824 | return EBUSY; | |
825 | } | 825 | } | |
826 | 826 | |||
827 | /* | 827 | /* | |
828 | * sector number and command | 828 | * sector number and command | |
829 | */ | 829 | */ | |
830 | sc->sc_dr->MPULBAREG = Lba; | 830 | sc->sc_dr->MPULBAREG = Lba; | |
831 | sc->sc_dr->SECCNTCMDREG = | 831 | sc->sc_dr->SECCNTCMDREG = | |
832 | (uint16_t)(Command | (nSectors & SAC_SECCCNT)); | 832 | (uint16_t)(Command | (nSectors & SAC_SECCCNT)); | |
833 | 833 | |||
834 | /* | 834 | /* | |
835 | * re-route the chip | 835 | * re-route the chip | |
836 | * NB: The "RESET" is actually not much of a misnomer. | 836 | * NB: The "RESET" is actually not much of a misnomer. | |
837 | * The chip was designed for a one-shot execution at reset time, | 837 | * The chip was designed for a one-shot execution at reset time, | |
838 | * namely loading the configuration data into the FPGA. So. | 838 | * namely loading the configuration data into the FPGA. So. | |
839 | */ | 839 | */ | |
840 | sc->hw_busy = TRUE; | 840 | sc->hw_busy = TRUE; | |
841 | sc->sc_dr->CONTROLREG |= SAC_CFGRESET; | 841 | sc->sc_dr->CONTROLREG |= SAC_CFGRESET; | |
842 | return 0; | 842 | return 0; | |
843 | } | 843 | } | |
844 | 844 | |||
845 | /* | 845 | /* | |
846 | * Identify the (size of the) CompactFlash card inserted in the slot. | 846 | * Identify the (size of the) CompactFlash card inserted in the slot. | |
847 | */ | 847 | */ | |
848 | static int | 848 | static int | |
849 | sysace_identify(struct ace_softc *sc) | 849 | sysace_identify(struct ace_softc *sc) | |
850 | { | 850 | { | |
851 | PCFLASH_IDENTIFY Identify = &sc->sc_params; | 851 | PCFLASH_IDENTIFY Identify = &sc->sc_params; | |
852 | uint32_t Status = 0; | 852 | uint32_t Status = 0; | |
853 | int i, j, error; | 853 | int i, j, error; | |
854 | 854 | |||
855 | DBGME(DEBUG_FUNCS, printf("Sysace::Identify %p\n", sc)); | 855 | DBGME(DEBUG_FUNCS, printf("Sysace::Identify %p\n", sc)); | |
856 | 856 | |||
857 | /* | 857 | /* | |
858 | * Turn on interrupts before we start the command | 858 | * Turn on interrupts before we start the command | |
859 | */ | 859 | */ | |
860 | sysace_inton(sc); /* BUGBUG we should add polling mode (for dump too) */ | 860 | sysace_inton(sc); /* BUGBUG we should add polling mode (for dump too) */ | |
861 | 861 | |||
862 | /* | 862 | /* | |
863 | * This will invalidate the ACE's current sector data | 863 | * This will invalidate the ACE's current sector data | |
864 | */ | 864 | */ | |
865 | sc->sc_capacity = 0; | 865 | sc->sc_capacity = 0; | |
866 | 866 | |||
867 | /* | 867 | /* | |
868 | * Get it going | 868 | * Get it going | |
869 | */ | 869 | */ | |
870 | error = sysace_start(sc, SAC_CMD_IDENTIFYMEMCARD, 0, 1); | 870 | error = sysace_start(sc, SAC_CMD_IDENTIFYMEMCARD, 0, 1); | |
871 | 871 | |||
872 | /* | 872 | /* | |
873 | * Wait until its done | 873 | * Wait until its done | |
874 | */ | 874 | */ | |
875 | if (!FAILED(error)) { | 875 | if (!FAILED(error)) { | |
876 | 876 | |||
877 | /* Might be called during autoconf, no interrupts */ | 877 | /* Might be called during autoconf, no interrupts */ | |
878 | if (cold) { | 878 | if (cold) { | |
879 | do { | 879 | do { | |
880 | DELAY(10); | 880 | DELAY(10); | |
881 | Status = sc->sc_dr->STATUS; | 881 | Status = sc->sc_dr->STATUS; | |
882 | } while ((Status & | 882 | } while ((Status & | |
883 | (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)) == 0); | 883 | (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)) == 0); | |
884 | } else { | 884 | } else { | |
885 | while (sc->hw_busy) { | 885 | while (sc->hw_busy) { | |
886 | DBGME(DEBUG_FUNCS, | 886 | DBGME(DEBUG_FUNCS, | |
887 | printf("Sysace:: cwait.. (st=%x)" | 887 | printf("Sysace:: cwait.. (st=%x)" | |
888 | " sizeof=%d\n", | 888 | " sizeof=%d\n", | |
889 | sc->sc_dr->STATUS, sizeof(*Identify))); | 889 | sc->sc_dr->STATUS, sizeof(*Identify))); | |
890 | error = tsleep(&sc->media_has_changed, PRIBIO, | 890 | error = tsleep(&sc->media_has_changed, PRIBIO, | |
891 | "aceidfy", 0); | 891 | "aceidfy", 0); | |
892 | } | 892 | } | |
893 | } | 893 | } | |
894 | 894 | |||
895 | /* | 895 | /* | |
896 | * Did it work? | 896 | * Did it work? | |
897 | */ | 897 | */ | |
898 | Status = sc->sc_dr->STATUS; | 898 | Status = sc->sc_dr->STATUS; | |
899 | 899 | |||
900 | if (Status & SAC_DATABUFRDY) { | 900 | if (Status & SAC_DATABUFRDY) { | |
901 | 901 | |||
902 | /* | 902 | /* | |
903 | * Yes, pull out all the data. | 903 | * Yes, pull out all the data. | |
904 | * NB: Until we do so the chip will not be ready for | 904 | * NB: Until we do so the chip will not be ready for | |
905 | * another command | 905 | * another command | |
906 | */ | 906 | */ | |
907 | for (i = 0; i < sizeof(*Identify); i += 4) { | 907 | for (i = 0; i < sizeof(*Identify); i += 4) { | |
908 | 908 | |||
909 | /* | 909 | /* | |
910 | * Verify the (32-bytes) FIFO has reloaded | 910 | * Verify the (32-bytes) FIFO has reloaded | |
911 | */ | 911 | */ | |
912 | for (j = 0; j < 10; j++) { | 912 | for (j = 0; j < 10; j++) { | |
913 | Status = sc->sc_dr->STATUS; | 913 | Status = sc->sc_dr->STATUS; | |
914 | if (Status & SAC_DATABUFRDY) | 914 | if (Status & SAC_DATABUFRDY) | |
915 | break; | 915 | break; | |
916 | DELAY(10); | 916 | DELAY(10); | |
917 | } | 917 | } | |
918 | if (Status & SAC_DATABUFRDY) { | 918 | if (Status & SAC_DATABUFRDY) { | |
919 | uint32_t Data32; | 919 | uint32_t Data32; | |
920 | 920 | |||
921 | /* | 921 | /* | |
922 | * This pulls two 16-bit words out of | 922 | * This pulls two 16-bit words out of | |
923 | * the FIFO. | 923 | * the FIFO. | |
924 | * They are ordered in LE. | 924 | * They are ordered in LE. | |
925 | * NB: Yes this is different from | 925 | * NB: Yes this is different from | |
926 | * regular data accesses | 926 | * regular data accesses | |
927 | */ | 927 | */ | |
928 | Data32 = sc->sc_dr->DATABUFREG[0]; | 928 | Data32 = sc->sc_dr->DATABUFREG[0]; | |
929 | #if _BYTE_ORDER == _LITTLE_ENDIAN | 929 | #if _BYTE_ORDER == _LITTLE_ENDIAN | |
930 | /* all is fine */ | 930 | /* all is fine */ | |
931 | #else | 931 | #else | |
932 | Data32 = | 932 | Data32 = | |
933 | (Data32 >> 16) | (Data32 << 16); | 933 | (Data32 >> 16) | (Data32 << 16); | |
934 | #endif | 934 | #endif | |
935 | memcpy(((char *)Identify) + i, | 935 | memcpy(((char *)Identify) + i, | |
936 | &Data32, 4); | 936 | &Data32, 4); | |
937 | } else { | 937 | } else { | |
938 | /* | 938 | /* | |
939 | * Ooops, what's going on here? | 939 | * Ooops, what's going on here? | |
940 | */ | 940 | */ | |
941 | DBGME(DEBUG_ERRORS, | 941 | DBGME(DEBUG_ERRORS, | |
942 | printf("Sysace::!DATABUFRDY %x\n", | 942 | printf("Sysace::!DATABUFRDY %x\n", | |
943 | Status)); | 943 | Status)); | |
944 | error = EIO; | 944 | error = EIO; | |
945 | break; | 945 | break; | |
946 | } | 946 | } | |
947 | } | 947 | } | |
948 | 948 | |||
949 | /* | 949 | /* | |
950 | * Make sure we did ok and pick up the relevant info | 950 | * Make sure we did ok and pick up the relevant info | |
951 | */ | 951 | */ | |
952 | if (Status & SAC_DATABUFRDY) { | 952 | if (Status & SAC_DATABUFRDY) { | |
953 | DBGME(DEBUG_XFERS, | 953 | DBGME(DEBUG_XFERS, | |
954 | device_printf(sc->sc_dev, | 954 | device_printf(sc->sc_dev, | |
955 | "model: %.40s/%.20s\n", | 955 | "model: %.40s/%.20s\n", | |
956 | Identify->ModelNumber, | 956 | Identify->ModelNumber, | |
957 | Identify->SerialNumber)); | 957 | Identify->SerialNumber)); | |
958 | if (Identify->Signature == CFLASH_SIGNATURE) { | 958 | if (Identify->Signature == CFLASH_SIGNATURE) { | |
959 | DBGME(DEBUG_PROBE, | 959 | DBGME(DEBUG_PROBE, | |
960 | printf("Sysace::Card is" | 960 | printf("Sysace::Card is" | |
961 | " %.40s::%.20s\n", | 961 | " %.40s::%.20s\n", | |
962 | Identify->ModelNumber, | 962 | Identify->ModelNumber, | |
963 | Identify->SerialNumber)); | 963 | Identify->SerialNumber)); | |
964 | 964 | |||
965 | sc->sc_capacity = | 965 | sc->sc_capacity = | |
966 | (Identify->SectorsPerCard[0] << 16) | 966 | (Identify->SectorsPerCard[0] << 16) | |
967 | | Identify->SectorsPerCard[1]; | 967 | | Identify->SectorsPerCard[1]; | |
968 | DBGME(DEBUG_PROBE, | 968 | DBGME(DEBUG_PROBE, | |
969 | printf("Sysace::sc_capacity x%qx\n", | 969 | printf("Sysace::sc_capacity x%qx\n", | |
970 | sc->sc_capacity)); | 970 | sc->sc_capacity)); | |
971 | ace_set_geometry(sc); | 971 | ace_set_geometry(sc); | |
972 | } else { | 972 | } else { | |
973 | DBGME(DEBUG_ERRORS, | 973 | DBGME(DEBUG_ERRORS, | |
974 | printf("Sysace::Bad card signature?" | 974 | printf("Sysace::Bad card signature?" | |
975 | " %x != %x\n", | 975 | " %x != %x\n", | |
976 | Identify->Signature, | 976 | Identify->Signature, | |
977 | CFLASH_SIGNATURE)); | 977 | CFLASH_SIGNATURE)); | |
978 | sc->sc_capacity = 0; | 978 | sc->sc_capacity = 0; | |
979 | error = ENXIO; | 979 | error = ENXIO; | |
980 | } | 980 | } | |
981 | } else { | 981 | } else { | |
982 | error = ETIMEDOUT; | 982 | error = ETIMEDOUT; | |
983 | } | 983 | } | |
984 | } else { | 984 | } else { | |
985 | /* | 985 | /* | |
986 | * No, it did not work. Maybe there is no card inserted | 986 | * No, it did not work. Maybe there is no card inserted | |
987 | */ | 987 | */ | |
988 | DBGME(DEBUG_ERRORS, | 988 | DBGME(DEBUG_ERRORS, | |
989 | printf("Sysace::Identify failed," | 989 | printf("Sysace::Identify failed," | |
990 | " missing CFLASH card?\n")); | 990 | " missing CFLASH card?\n")); | |
991 | SysaceDumpRegisters(sc->sc_dr); | 991 | SysaceDumpRegisters(sc->sc_dr); | |
992 | /* BUGBUG Fix the error code accordingly */ | 992 | /* BUGBUG Fix the error code accordingly */ | |
993 | error = ETIMEDOUT; | 993 | error = ETIMEDOUT; | |
994 | } | 994 | } | |
995 | } | 995 | } | |
996 | 996 | |||
997 | /* remember this jic */ | 997 | /* remember this jic */ | |
998 | sc->sc_bio.r_error = Status; | 998 | sc->sc_bio.r_error = Status; | |
999 | 999 | |||
1000 | /* Free the ACE for the JTAG, just in case */ | 1000 | /* Free the ACE for the JTAG, just in case */ | |
1001 | sysace_unlock_registers(sc); | 1001 | sysace_unlock_registers(sc); | |
1002 | 1002 | |||
1003 | /* | 1003 | /* | |
1004 | * Done | 1004 | * Done | |
1005 | */ | 1005 | */ | |
1006 | return error; | 1006 | return error; | |
1007 | } | 1007 | } | |
1008 | 1008 | |||
1009 | /* | 1009 | /* | |
1010 | * Common code for read&write argument validation | 1010 | * Common code for read&write argument validation | |
1011 | */ | 1011 | */ | |
1012 | static int | 1012 | static int | |
1013 | sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize) | 1013 | sysace_validate(struct ace_softc *sc, daddr_t start, size_t *pSize) | |
1014 | { | 1014 | { | |
1015 | daddr_t Size; | 1015 | daddr_t Size; | |
1016 | 1016 | |||
1017 | /* | 1017 | /* | |
1018 | * Verify that we know the media size | 1018 | * Verify that we know the media size | |
1019 | */ | 1019 | */ | |
1020 | if (sc->sc_capacity == 0) { | 1020 | if (sc->sc_capacity == 0) { | |
1021 | int error = sysace_identify(sc); | 1021 | int error = sysace_identify(sc); | |
1022 | if (FAILED(error)) | 1022 | if (FAILED(error)) | |
1023 | return error; | 1023 | return error; | |
1024 | } | 1024 | } | |
1025 | 1025 | |||
1026 | /* | 1026 | /* | |
1027 | * Validate args | 1027 | * Validate args | |
1028 | */ | 1028 | */ | |
1029 | if (start >= sc->sc_capacity) { | 1029 | if (start >= sc->sc_capacity) { | |
1030 | *pSize = 0; | 1030 | *pSize = 0; | |
1031 | DBGME(DEBUG_ERRORS, | 1031 | DBGME(DEBUG_ERRORS, | |
1032 | printf("Sysace::ValidateArg(%qx) EOF\n", start)); | 1032 | printf("Sysace::ValidateArg(%qx) EOF\n", start)); | |
1033 | return E2BIG; | 1033 | return E2BIG; | |
1034 | } | 1034 | } | |
1035 | 1035 | |||
1036 | /* | 1036 | /* | |
1037 | * Adjust size if necessary | 1037 | * Adjust size if necessary | |
1038 | */ | 1038 | */ | |
1039 | Size = start + *pSize; | 1039 | Size = start + *pSize; | |
1040 | if (Size > sc->sc_capacity) { | 1040 | if (Size > sc->sc_capacity) { | |
1041 | /* | 1041 | /* | |
1042 | * At most this many sectors | 1042 | * At most this many sectors | |
1043 | */ | 1043 | */ | |
1044 | Size = sc->sc_capacity - start; | 1044 | Size = sc->sc_capacity - start; | |
1045 | *pSize = (size_t)Size; | 1045 | *pSize = (size_t)Size; | |
1046 | } | 1046 | } | |
1047 | 1047 | |||
1048 | DBGME(DEBUG_FUNCS, | 1048 | DBGME(DEBUG_FUNCS, | |
1049 | printf("Sysace::Validate %qx %zd\n", start, *pSize)); | 1049 | printf("Sysace::Validate %qx %zd\n", start, *pSize)); | |
1050 | return 0; | 1050 | return 0; | |
1051 | } | 1051 | } | |
1052 | 1052 | |||
1053 | /* Read SIZE bytes from sysace device, at offset Position | 1053 | /* Read SIZE bytes from sysace device, at offset Position | |
1054 | */ | 1054 | */ | |
1055 | uint32_t ace_maxatatime = 255; | 1055 | uint32_t ace_maxatatime = 255; | |
1056 | #define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */ | 1056 | #define MAXATATIME ace_maxatatime //255 /* BUGBUG test me on real hardware!! */ | |
1057 | 1057 | |||
1058 | static int | 1058 | static int | |
1059 | sysace_read_at(struct ace_softc *sc, daddr_t start_sector, char *buffer, | 1059 | sysace_read_at(struct ace_softc *sc, daddr_t start_sector, char *buffer, | |
1060 | size_t nblocks, size_t *pSizeRead) | 1060 | size_t nblocks, size_t *pSizeRead) | |
1061 | { | 1061 | { | |
1062 | int error; | 1062 | int error; | |
1063 | uint32_t BlocksThisTime; | 1063 | uint32_t BlocksThisTime; | |
1064 | uint32_t Status = 0, SizeRead = 0; | 1064 | uint32_t Status = 0, SizeRead = 0; | |
1065 | uint32_t i, j; | 1065 | uint32_t i, j; | |
1066 | 1066 | |||
1067 | DBGME(DEBUG_XFERS|DEBUG_READS, | 1067 | DBGME(DEBUG_XFERS|DEBUG_READS, | |
1068 | printf("SysaceReadAt(%p %qx %p %zd %p)\n", | 1068 | printf("SysaceReadAt(%p %qx %p %zd %p)\n", | |
1069 | sc, start_sector, buffer, nblocks, pSizeRead)); | 1069 | sc, start_sector, buffer, nblocks, pSizeRead)); | |
1070 | 1070 | |||
1071 | /* | 1071 | /* | |
1072 | * Validate & trim arguments | 1072 | * Validate & trim arguments | |
1073 | */ | 1073 | */ | |
1074 | error = sysace_validate(sc, start_sector, &nblocks); | 1074 | error = sysace_validate(sc, start_sector, &nblocks); | |
1075 | 1075 | |||
1076 | /* | 1076 | /* | |
1077 | * Repeat until we are done or error | 1077 | * Repeat until we are done or error | |
1078 | */ | 1078 | */ | |
1079 | while (error == 0) { | 1079 | while (error == 0) { | |
1080 | 1080 | |||
1081 | /* | 1081 | /* | |
1082 | * .. one bunch of sectors at a time | 1082 | * .. one bunch of sectors at a time | |
1083 | */ | 1083 | */ | |
1084 | BlocksThisTime = nblocks; | 1084 | BlocksThisTime = nblocks; | |
1085 | if (BlocksThisTime > MAXATATIME) | 1085 | if (BlocksThisTime > MAXATATIME) | |
1086 | BlocksThisTime = MAXATATIME; | 1086 | BlocksThisTime = MAXATATIME; | |
1087 | 1087 | |||
1088 | /* | 1088 | /* | |
1089 | * Yes, start a sector read | 1089 | * Yes, start a sector read | |
1090 | */ | 1090 | */ | |
1091 | sysace_inton(sc); | 1091 | sysace_inton(sc); | |
1092 | error = sysace_start(sc, | 1092 | error = sysace_start(sc, | |
1093 | SAC_CMD_READMEMCARDDATA, | 1093 | SAC_CMD_READMEMCARDDATA, | |
1094 | (uint32_t)start_sector, /* BUGBUG trims here, no warn. */ | 1094 | (uint32_t)start_sector, /* BUGBUG trims here, no warn. */ | |
1095 | BlocksThisTime); | 1095 | BlocksThisTime); | |
1096 | /* | 1096 | /* | |
1097 | * And wait until done, if ok | 1097 | * And wait until done, if ok | |
1098 | */ | 1098 | */ | |
1099 | if (!FAILED(error)) { | 1099 | if (!FAILED(error)) { | |
1100 | start_sector += BlocksThisTime; | 1100 | start_sector += BlocksThisTime; | |
1101 | /* Might be called during autoconf, no interrupts */ | 1101 | /* Might be called during autoconf, no interrupts */ | |
1102 | /* BUGBUG timeouts! */ | 1102 | /* BUGBUG timeouts! */ | |
1103 | if (cold) { | 1103 | if (cold) { | |
1104 | do { | 1104 | do { | |
1105 | DELAY(10); | 1105 | DELAY(10); | |
1106 | Status = sc->sc_dr->STATUS; | 1106 | Status = sc->sc_dr->STATUS; | |
1107 | } while ((Status & | 1107 | } while ((Status & | |
1108 | (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)) | 1108 | (SAC_DATABUFRDY|SAC_CFCERROR|SAC_CFGERROR)) | |
1109 | == 0); | 1109 | == 0); | |
1110 | } else { | 1110 | } else { | |
1111 | while (sc->hw_busy) { | 1111 | while (sc->hw_busy) { | |
1112 | error = tsleep(&sc->media_has_changed, | 1112 | error = tsleep(&sc->media_has_changed, | |
1113 | PRIBIO, "aceread", 0); | 1113 | PRIBIO, "aceread", 0); | |
1114 | } | 1114 | } | |
1115 | } | 1115 | } | |
1116 | } | 1116 | } | |
1117 | 1117 | |||
1118 | /* | 1118 | /* | |
1119 | * Are we doing ok | 1119 | * Are we doing ok | |
1120 | */ | 1120 | */ | |
1121 | if (!FAILED(error)) { | 1121 | if (!FAILED(error)) { | |
1122 | 1122 | |||
1123 | /* | 1123 | /* | |
1124 | * Get the data out of the ACE | 1124 | * Get the data out of the ACE | |
1125 | */ | 1125 | */ | |
1126 | for (i = 0; i < (BlocksThisTime << CF_SECBITS); | 1126 | for (i = 0; i < (BlocksThisTime << CF_SECBITS); | |
1127 | i += 4) { | 1127 | i += 4) { | |
1128 | 1128 | |||
1129 | /* | 1129 | /* | |
1130 | * Make sure the FIFO is ready | 1130 | * Make sure the FIFO is ready | |
1131 | */ | 1131 | */ | |
1132 | for (j = 0; j < 10; j++) { | 1132 | for (j = 0; j < 10; j++) { | |
1133 | Status = sc->sc_dr->STATUS; | 1133 | Status = sc->sc_dr->STATUS; | |
1134 | if (Status & SAC_DATABUFRDY) | 1134 | if (Status & SAC_DATABUFRDY) | |
1135 | break; | 1135 | break; | |
1136 | DELAY(1000); | 1136 | DELAY(1000); | |
1137 | } | 1137 | } | |
1138 | 1138 | |||
1139 | /* | 1139 | /* | |
1140 | * Got it? | 1140 | * Got it? | |
1141 | */ | 1141 | */ | |
1142 | if (Status & SAC_DATABUFRDY) { | 1142 | if (Status & SAC_DATABUFRDY) { | |
1143 | uint32_t Data32; | 1143 | uint32_t Data32; | |
1144 | 1144 | |||
1145 | Data32 = sc->sc_dr->DATABUFREG[0]; | 1145 | Data32 = sc->sc_dr->DATABUFREG[0]; | |
1146 | Data32 = le32toh(Data32); | 1146 | Data32 = le32toh(Data32); | |
1147 | memcpy(buffer + i, &Data32, 4); | 1147 | memcpy(buffer + i, &Data32, 4); | |
1148 | } else { | 1148 | } else { | |
1149 | /* | 1149 | /* | |
1150 | * Ooops, get out of here | 1150 | * Ooops, get out of here | |
1151 | */ | 1151 | */ | |
1152 | DBGME(DEBUG_ERRORS, | 1152 | DBGME(DEBUG_ERRORS, | |
1153 | printf("Sysace::READ timeout\n")); | 1153 | printf("Sysace::READ timeout\n")); | |
1154 | SysaceDumpRegisters(sc->sc_dr); | 1154 | SysaceDumpRegisters(sc->sc_dr); | |
1155 | error = ETIMEDOUT; | 1155 | error = ETIMEDOUT; | |
1156 | break; | 1156 | break; | |
1157 | } | 1157 | } | |
1158 | } | 1158 | } | |
1159 | 1159 | |||
1160 | /* | 1160 | /* | |
1161 | * Still doing ok? | 1161 | * Still doing ok? | |
1162 | */ | 1162 | */ | |
1163 | if (!FAILED(error)) { | 1163 | if (!FAILED(error)) { | |
1164 | nblocks -= BlocksThisTime; | 1164 | nblocks -= BlocksThisTime; | |
1165 | SizeRead += BlocksThisTime; | 1165 | SizeRead += BlocksThisTime; | |
1166 | buffer += BlocksThisTime << CF_SECBITS; | 1166 | buffer += BlocksThisTime << CF_SECBITS; | |
1167 | } else { | 1167 | } else { | |
1168 | /* remember this jic */ | 1168 | /* remember this jic */ | |
1169 | sc->sc_bio.r_error = Status; | 1169 | sc->sc_bio.r_error = Status; | |
1170 | } | 1170 | } | |
1171 | } | 1171 | } | |
1172 | 1172 | |||
1173 | /* Free the ACE for the JTAG, just in case */ | 1173 | /* Free the ACE for the JTAG, just in case */ | |
1174 | sysace_unlock_registers(sc); | 1174 | sysace_unlock_registers(sc); | |
1175 | 1175 | |||
1176 | /* | 1176 | /* | |
1177 | * Are we done yet? | 1177 | * Are we done yet? | |
1178 | */ | 1178 | */ | |
1179 | if (nblocks == 0) | 1179 | if (nblocks == 0) | |
1180 | break; | 1180 | break; | |
1181 | } | 1181 | } | |
1182 | 1182 | |||
1183 | if (pSizeRead) | 1183 | if (pSizeRead) | |
1184 | *pSizeRead = SizeRead; | 1184 | *pSizeRead = SizeRead; | |
1185 | return error; | 1185 | return error; | |
1186 | } | 1186 | } | |
1187 | 1187 | |||
1188 | /* | 1188 | /* | |
1189 | * Write SIZE bytes to device. | 1189 | * Write SIZE bytes to device. | |
1190 | */ | 1190 | */ | |
1191 | static int | 1191 | static int | |
1192 | sysace_write_at(struct ace_softc *sc, daddr_t start_sector, char *buffer, | 1192 | sysace_write_at(struct ace_softc *sc, daddr_t start_sector, char *buffer, | |
1193 | size_t nblocks, size_t *pSizeWritten) | 1193 | size_t nblocks, size_t *pSizeWritten) | |
1194 | { | 1194 | { | |
1195 | int error; | 1195 | int error; | |
1196 | uint32_t BlocksThisTime; | 1196 | uint32_t BlocksThisTime; | |
1197 | uint32_t Status = 0, SizeWritten = 0; | 1197 | uint32_t Status = 0, SizeWritten = 0; | |
1198 | uint32_t i, j; | 1198 | uint32_t i, j; | |
1199 | 1199 | |||
1200 | DBGME(DEBUG_XFERS|DEBUG_WRITES, | 1200 | DBGME(DEBUG_XFERS|DEBUG_WRITES, | |
1201 | printf("SysaceWriteAt(%p %qx %p %zd %p)\n", | 1201 | printf("SysaceWriteAt(%p %qx %p %zd %p)\n", | |
1202 | sc, start_sector, buffer, nblocks, pSizeWritten)); | 1202 | sc, start_sector, buffer, nblocks, pSizeWritten)); | |
1203 | 1203 | |||
1204 | /* | 1204 | /* | |
1205 | * Validate & trim arguments | 1205 | * Validate & trim arguments | |
1206 | */ | 1206 | */ | |
1207 | error = sysace_validate(sc, start_sector, &nblocks); | 1207 | error = sysace_validate(sc, start_sector, &nblocks); | |
1208 | 1208 | |||
1209 | /* | 1209 | /* | |
1210 | * Repeat until we are done or error | 1210 | * Repeat until we are done or error | |
1211 | */ | 1211 | */ | |
1212 | while (error == 0) { | 1212 | while (error == 0) { | |
1213 | 1213 | |||
1214 | /* | 1214 | /* | |
1215 | * .. one sector at a time | 1215 | * .. one sector at a time | |
1216 | * BUGBUG Supposedly we can do up to 256 sectors? | 1216 | * BUGBUG Supposedly we can do up to 256 sectors? | |
1217 | */ | 1217 | */ | |
1218 | BlocksThisTime = nblocks; | 1218 | BlocksThisTime = nblocks; | |
1219 | if (BlocksThisTime > MAXATATIME) | 1219 | if (BlocksThisTime > MAXATATIME) | |
1220 | BlocksThisTime = MAXATATIME; | 1220 | BlocksThisTime = MAXATATIME; | |
1221 | 1221 | |||
1222 | /* | 1222 | /* | |
1223 | * Yes, start a sector write | 1223 | * Yes, start a sector write | |
1224 | */ | 1224 | */ | |
1225 | sysace_inton(sc); | 1225 | sysace_inton(sc); | |
1226 | error = sysace_start(sc, | 1226 | error = sysace_start(sc, | |
1227 | SAC_CMD_WRITEMEMCARDDATA, | 1227 | SAC_CMD_WRITEMEMCARDDATA, | |
1228 | (uint32_t)start_sector, /* BUGBUG trims here, no warn. */ | 1228 | (uint32_t)start_sector, /* BUGBUG trims here, no warn. */ | |
1229 | BlocksThisTime); | 1229 | BlocksThisTime); | |
1230 | /* | 1230 | /* | |
1231 | * And wait until done, if ok | 1231 | * And wait until done, if ok | |
1232 | */ | 1232 | */ | |
1233 | if (!FAILED(error)) { | 1233 | if (!FAILED(error)) { | |
1234 | start_sector += BlocksThisTime; | 1234 | start_sector += BlocksThisTime; | |
1235 | /* BUGBUG timeouts! */ | 1235 | /* BUGBUG timeouts! */ | |
1236 | while (sc->hw_busy) { | 1236 | while (sc->hw_busy) { | |
1237 | error = tsleep(&sc->media_has_changed, | 1237 | error = tsleep(&sc->media_has_changed, | |
1238 | PRIBIO, "acewrite", 0); | 1238 | PRIBIO, "acewrite", 0); | |
1239 | } | 1239 | } | |
1240 | } | 1240 | } | |
1241 | 1241 | |||
1242 | /* | 1242 | /* | |
1243 | * Are we doing ok | 1243 | * Are we doing ok | |
1244 | */ | 1244 | */ | |
1245 | if (!FAILED(error)) { | 1245 | if (!FAILED(error)) { | |
1246 | 1246 | |||
1247 | /* | 1247 | /* | |
1248 | * Get the data out to the ACE | 1248 | * Get the data out to the ACE | |
1249 | */ | 1249 | */ | |
1250 | for (i = 0; i < (BlocksThisTime << CF_SECBITS); | 1250 | for (i = 0; i < (BlocksThisTime << CF_SECBITS); | |
1251 | i += 4) { | 1251 | i += 4) { | |
1252 | 1252 | |||
1253 | /* | 1253 | /* | |
1254 | * Make sure the FIFO is ready | 1254 | * Make sure the FIFO is ready | |
1255 | */ | 1255 | */ | |
1256 | for (j = 0; j < 10; j++) { | 1256 | for (j = 0; j < 10; j++) { | |
1257 | Status = sc->sc_dr->STATUS; | 1257 | Status = sc->sc_dr->STATUS; | |
1258 | if (Status & SAC_DATABUFRDY) | 1258 | if (Status & SAC_DATABUFRDY) | |
1259 | break; | 1259 | break; | |
1260 | DELAY(1000); | 1260 | DELAY(1000); | |
1261 | } | 1261 | } | |
1262 | 1262 | |||
1263 | /* | 1263 | /* | |
1264 | * Got it? | 1264 | * Got it? | |
1265 | */ | 1265 | */ | |
1266 | if (Status & SAC_DATABUFRDY) { | 1266 | if (Status & SAC_DATABUFRDY) { | |
1267 | uint32_t Data32; | 1267 | uint32_t Data32; | |
1268 | 1268 | |||
1269 | memcpy(&Data32, buffer + i, 4); | 1269 | memcpy(&Data32, buffer + i, 4); | |
1270 | Data32 = htole32(Data32); | 1270 | Data32 = htole32(Data32); | |
1271 | sc->sc_dr->DATABUFREG[0] = Data32; | 1271 | sc->sc_dr->DATABUFREG[0] = Data32; | |
1272 | } else { | 1272 | } else { | |
1273 | /* | 1273 | /* | |
1274 | * Ooops, get out of here | 1274 | * Ooops, get out of here | |
1275 | */ | 1275 | */ | |
1276 | DBGME(DEBUG_ERRORS, | 1276 | DBGME(DEBUG_ERRORS, | |
1277 | printf("Sysace::WRITE timeout\n")); | 1277 | printf("Sysace::WRITE timeout\n")); | |
1278 | SysaceDumpRegisters(sc->sc_dr); | 1278 | SysaceDumpRegisters(sc->sc_dr); | |
1279 | error = ETIMEDOUT; | 1279 | error = ETIMEDOUT; | |
1280 | /* remember this jic */ | 1280 | /* remember this jic */ | |
1281 | sc->sc_bio.r_error = Status; | 1281 | sc->sc_bio.r_error = Status; | |
1282 | break; | 1282 | break; | |
1283 | } | 1283 | } | |
1284 | } | 1284 | } | |
1285 | 1285 | |||
1286 | /* | 1286 | /* | |
1287 | * Still doing ok? | 1287 | * Still doing ok? | |
1288 | */ | 1288 | */ | |
1289 | if (!FAILED(error)) { | 1289 | if (!FAILED(error)) { | |
1290 | nblocks -= BlocksThisTime; | 1290 | nblocks -= BlocksThisTime; | |
1291 | SizeWritten += BlocksThisTime; | 1291 | SizeWritten += BlocksThisTime; | |
1292 | buffer += BlocksThisTime << CF_SECBITS; | 1292 | buffer += BlocksThisTime << CF_SECBITS; | |
1293 | } | 1293 | } | |
1294 | } | 1294 | } | |
1295 | 1295 | |||
1296 | /* | 1296 | /* | |
1297 | * We need to wait until the device is ready for the | 1297 | * We need to wait until the device is ready for the | |
1298 | * next command | 1298 | * next command | |
1299 | * Experimentation shows that it can take longer than 10msec. | 1299 | * Experimentation shows that it can take longer than 10msec. | |
1300 | */ | 1300 | */ | |
1301 | if (!FAILED(error)) { | 1301 | if (!FAILED(error)) { | |
1302 | for (j = 0; j < 300; j++) { | 1302 | for (j = 0; j < 300; j++) { | |
1303 | Status = sc->sc_dr->STATUS; | 1303 | Status = sc->sc_dr->STATUS; | |
1304 | if (Status & SAC_RDYFORCFCMD) | 1304 | if (Status & SAC_RDYFORCFCMD) | |
1305 | break; | 1305 | break; | |
1306 | (void)tsleep(&sc->media_has_changed, | 1306 | (void)tsleep(&sc->media_has_changed, | |
1307 | PRIBIO, "acewrite", 2); | 1307 | PRIBIO, "acewrite", 2); | |
1308 | } | 1308 | } | |
1309 | if (!(Status & SAC_RDYFORCFCMD)) { | 1309 | if (!(Status & SAC_RDYFORCFCMD)) { | |
1310 | DBGME(DEBUG_ERRORS, | 1310 | DBGME(DEBUG_ERRORS, | |
1311 | printf("Sysace::WRITE-COMPLETE timeout" | 1311 | printf("Sysace::WRITE-COMPLETE timeout" | |
1312 | " St=%x\n", Status)); | 1312 | " St=%x\n", Status)); | |
1313 | SysaceDumpRegisters(sc->sc_dr); | 1313 | SysaceDumpRegisters(sc->sc_dr); | |
1314 | /* | 1314 | /* | |
1315 | * Ignore, we'll handle it the next time around | 1315 | * Ignore, we'll handle it the next time around | |
1316 | * BUGBUG To be revised along with non-existant | 1316 | * BUGBUG To be revised along with non-existant | |
1317 | * error handling | 1317 | * error handling | |
1318 | */ | 1318 | */ | |
1319 | } | 1319 | } | |
1320 | } | 1320 | } | |
1321 | 1321 | |||
1322 | /* Free the ACE for the JTAG, just in case */ | 1322 | /* Free the ACE for the JTAG, just in case */ | |
1323 | sysace_unlock_registers(sc); | 1323 | sysace_unlock_registers(sc); | |
1324 | 1324 | |||
1325 | /* | 1325 | /* | |
1326 | * Are we done yet? | 1326 | * Are we done yet? | |
1327 | */ | 1327 | */ | |
1328 | if (nblocks == 0) | 1328 | if (nblocks == 0) | |
1329 | break; | 1329 | break; | |
1330 | } | 1330 | } | |
1331 | 1331 | |||
1332 | if (pSizeWritten) | 1332 | if (pSizeWritten) | |
1333 | *pSizeWritten = SizeWritten; | 1333 | *pSizeWritten = SizeWritten; | |
1334 | return error; | 1334 | return error; | |
1335 | } | 1335 | } | |
1336 | 1336 | |||
1337 | int | 1337 | int | |
1338 | ace_ebus_intr(void *cookie, void *f) | 1338 | ace_ebus_intr(void *cookie, void *f) | |
1339 | { | 1339 | { | |
1340 | struct ace_softc *sc = cookie; | 1340 | struct ace_softc *sc = cookie; | |
1341 | uint32_t Control; | 1341 | uint32_t Control; | |
1342 | 1342 | |||
1343 | /* | 1343 | /* | |
1344 | * Turn off interrupts and ACK them | 1344 | * Turn off interrupts and ACK them | |
1345 | */ | 1345 | */ | |
1346 | sysace_intoff(sc); | 1346 | sysace_intoff(sc); | |
1347 | 1347 | |||
1348 | Control = sc->sc_dr->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS)); | 1348 | Control = sc->sc_dr->CONTROLREG & (~(SAC_RESETIRQ|SAC_INTERRUPTS)); | |
1349 | sc->sc_dr->CONTROLREG = Control | SAC_RESETIRQ; | 1349 | sc->sc_dr->CONTROLREG = Control | SAC_RESETIRQ; | |
1350 | sc->sc_dr->CONTROLREG = Control; | 1350 | sc->sc_dr->CONTROLREG = Control; | |
1351 | 1351 | |||
1352 | /* ... read status and do whatever ... */ | 1352 | /* ... read status and do whatever ... */ | |
1353 | 1353 | |||
1354 | sc->hw_busy = FALSE; | 1354 | sc->hw_busy = FALSE; | |
1355 | wakeup(&sc->media_has_changed); | 1355 | wakeup(&sc->media_has_changed); | |
1356 | return 1; | 1356 | return 1; | |
1357 | } | 1357 | } | |
1358 | 1358 | |||
1359 | #ifdef USE_ACE_FOR_RECONFIG | 1359 | #ifdef USE_ACE_FOR_RECONFIG | |
1360 | static int | 1360 | static int | |
1361 | sysace_send_config(struct ace_softc *sc, uint32_t *Data, unsigned int nBytes) | 1361 | sysace_send_config(struct ace_softc *sc, uint32_t *Data, unsigned int nBytes) | |
1362 | { | 1362 | { | |
1363 | struct _Sac *Interface = sc->sc_dr; | 1363 | struct _Sac *Interface = sc->sc_dr; | |
1364 | unsigned int i, j, nWords; | 1364 | unsigned int i, j, nWords; | |
1365 | uint32_t CtlWas; | 1365 | uint32_t CtlWas; | |
1366 | uint32_t Status; | 1366 | uint32_t Status; | |
1367 | 1367 | |||
1368 | CtlWas = Interface->CONTROLREG; | 1368 | CtlWas = Interface->CONTROLREG; | |
1369 | 1369 | |||
1370 | /* Set the bits but in RESET (pag 49-50 of specs)*/ | 1370 | /* Set the bits but in RESET (pag 49-50 of specs)*/ | |
1371 | #define CFGCMD (SAC_FORCELOCKREQ | SAC_LOCKREQ | SAC_CFGSEL | \ | 1371 | #define CFGCMD (SAC_FORCELOCKREQ | SAC_LOCKREQ | SAC_CFGSEL | \ | |
1372 | SAC_FORCECFGMODE |/* SAC_CFGMODE |*/ SAC_CFGSTART) | 1372 | SAC_FORCECFGMODE |/* SAC_CFGMODE |*/ SAC_CFGSTART) | |
1373 | 1373 | |||
1374 | Interface->CONTROLREG = CFGCMD | SAC_CFGRESET; | 1374 | Interface->CONTROLREG = CFGCMD | SAC_CFGRESET; | |
1375 | 1375 | |||
1376 | /* Take it out of RESET */ | 1376 | /* Take it out of RESET */ | |
1377 | Interface->CONTROLREG = CFGCMD; | 1377 | Interface->CONTROLREG = CFGCMD; | |
1378 | 1378 | |||
1379 | /* | 1379 | /* | |
1380 | * Must wait till it says READY | 1380 | * Must wait till it says READY | |
1381 | * It can take a looong time | 1381 | * It can take a looong time | |
1382 | */ | 1382 | */ | |
1383 | for (j = 0; j < 1000; j++) { | 1383 | for (j = 0; j < 1000; j++) { | |
1384 | Status = Interface->STATUS; | 1384 | Status = Interface->STATUS; | |
1385 | if (Status & SAC_RDYFORCFCMD) | 1385 | if (Status & SAC_RDYFORCFCMD) | |
1386 | break; | 1386 | break; | |
1387 | DELAY(1000); | 1387 | DELAY(1000); | |
1388 | } | 1388 | } | |
1389 | 1389 | |||
1390 | if (0 == (Status & SAC_RDYFORCFCMD)) { | 1390 | if (0 == (Status & SAC_RDYFORCFCMD)) { | |
1391 | DBGME(DEBUG_ERRORS, | 1391 | DBGME(DEBUG_ERRORS, | |
1392 | printf("Sysace::CMD error %x (j=%d)\n", Status, j)); | 1392 | printf("Sysace::CMD error %x (j=%d)\n", Status, j)); | |
1393 | goto Error; | 1393 | goto Error; | |
1394 | } | 1394 | } | |
1395 | 1395 | |||
1396 | /* | 1396 | /* | |
1397 | * Get the data out to the ACE | 1397 | * Get the data out to the ACE | |
1398 | */ | 1398 | */ | |
1399 | #define ACEROUNDUP 32 | 1399 | #define ACEROUNDUP 32 | |
1400 | nBytes = (nBytes + ACEROUNDUP - 1) & ~(ACEROUNDUP-1); | 1400 | nBytes = (nBytes + ACEROUNDUP - 1) & ~(ACEROUNDUP-1); | |
1401 | nWords = (nBytes + 3) / 4; | 1401 | nWords = (nBytes + 3) / 4; | |
1402 | DBGME(DEBUG_FUNCS, | 1402 | DBGME(DEBUG_FUNCS, | |
1403 | printf("Sending %d bytes (as %d words) to %p ", | 1403 | printf("Sending %d bytes (as %d words) to %p ", | |
1404 | nBytes, nWords, Interface)); | 1404 | nBytes, nWords, Interface)); | |
1405 | for (i = 0; i < nWords; i += 1/*word*/) { | 1405 | for (i = 0; i < nWords; i += 1/*word*/) { | |
1406 | 1406 | |||
1407 | /* Stop on errors */ | 1407 | /* Stop on errors */ | |
1408 | Status = Interface->ERRORREG; | 1408 | Status = Interface->ERRORREG; | |
1409 | if (Status) { | 1409 | if (Status) { | |
1410 | /* | 1410 | /* | |
1411 | * Ooops, get out of here | 1411 | * Ooops, get out of here | |
1412 | */ | 1412 | */ | |
1413 | DBGME(DEBUG_ERRORS, | 1413 | DBGME(DEBUG_ERRORS, | |
1414 | printf("Sysace::CFG error %x (i=%d)\n", Status, i)); | 1414 | printf("Sysace::CFG error %x (i=%d)\n", Status, i)); | |
1415 | goto Error; | 1415 | goto Error; | |
1416 | } | 1416 | } | |
1417 | 1417 | |||
1418 | /* | 1418 | /* | |
1419 | * Make sure the FIFO is ready | 1419 | * Make sure the FIFO is ready | |
1420 | */ | 1420 | */ | |
1421 | for (j = 0; j < 100; j++) { | 1421 | for (j = 0; j < 100; j++) { | |
1422 | Status = Interface->STATUS; | 1422 | Status = Interface->STATUS; | |
1423 | if (Status & SAC_DATABUFRDY) | 1423 | if (Status & SAC_DATABUFRDY) | |
1424 | break; | 1424 | break; | |
1425 | DELAY(1000); | 1425 | DELAY(1000); | |
1426 | } | 1426 | } | |
1427 | 1427 | |||
1428 | /* | 1428 | /* | |
1429 | * Got it? | 1429 | * Got it? | |
1430 | */ | 1430 | */ | |
1431 | if (Status & SAC_DATABUFRDY) { | 1431 | if (Status & SAC_DATABUFRDY) { | |
1432 | uint32_t Data32; | 1432 | uint32_t Data32; | |
1433 | 1433 | |||
1434 | Data32 = Data[i]; | 1434 | Data32 = Data[i]; | |
1435 | Data32 = htole32(Data32); | 1435 | Data32 = htole32(Data32); | |
1436 | Interface->DATABUFREG[0] = Data32; | 1436 | Interface->DATABUFREG[0] = Data32; | |
1437 | } else { | 1437 | } else { | |
1438 | /* | 1438 | /* | |
1439 | * Ooops, get out of here | 1439 | * Ooops, get out of here | |
1440 | */ | 1440 | */ | |
1441 | DBGME(DEBUG_ERRORS, | 1441 | DBGME(DEBUG_ERRORS, | |
1442 | printf("Sysace::WRITE timeout %x (i=%d)\n", | 1442 | printf("Sysace::WRITE timeout %x (i=%d)\n", | |
1443 | Status, i)); | 1443 | Status, i)); | |
1444 | goto Error; | 1444 | goto Error; | |
1445 | } | 1445 | } | |
1446 | } | 1446 | } | |
1447 | DBGME(DEBUG_FUNCS, printf("done ok.\n")); | 1447 | DBGME(DEBUG_FUNCS, printf("done ok.\n")); | |
1448 | 1448 | |||
1449 | /* Put it back the way it was (try to.. :-( )*/ | 1449 | /* Put it back the way it was (try to.. :-( )*/ | |
1450 | Interface->CONTROLREG = CtlWas; | 1450 | Interface->CONTROLREG = CtlWas; | |
1451 | return 0; | 1451 | return 0; | |
1452 | 1452 | |||
1453 | Error: | 1453 | Error: | |
1454 | SysaceDumpRegisters(Interface); | 1454 | SysaceDumpRegisters(Interface); | |
1455 | Interface->CONTROLREG = CtlWas; | 1455 | Interface->CONTROLREG = CtlWas; | |
1456 | return EIO; | 1456 | return EIO; | |
1457 | } | 1457 | } | |
1458 | #endif /* USE_ACE_FOR_RECONFIG */ | 1458 | #endif /* USE_ACE_FOR_RECONFIG */ | |
1459 | 1459 | |||
1460 | 1460 | |||
1461 | /* | 1461 | /* | |
1462 | * Rest of code lifted with mods from the dev\ata\wd.c driver | 1462 | * Rest of code lifted with mods from the dev\ata\wd.c driver | |
1463 | */ | 1463 | */ | |
1464 | 1464 | |||
1465 | /* | 1465 | /* | |
1466 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | 1466 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | |
1467 | * | 1467 | * | |
1468 | * Redistribution and use in source and binary forms, with or without | 1468 | * Redistribution and use in source and binary forms, with or without | |
1469 | * modification, are permitted provided that the following conditions | 1469 | * modification, are permitted provided that the following conditions | |
1470 | * are met: | 1470 | * are met: | |
1471 | * 1. Redistributions of source code must retain the above copyright | 1471 | * 1. Redistributions of source code must retain the above copyright | |
1472 | * notice, this list of conditions and the following disclaimer. | 1472 | * notice, this list of conditions and the following disclaimer. | |
1473 | * 2. Redistributions in binary form must reproduce the above copyright | 1473 | * 2. Redistributions in binary form must reproduce the above copyright | |
1474 | * notice, this list of conditions and the following disclaimer in the | 1474 | * notice, this list of conditions and the following disclaimer in the | |
1475 | * documentation and/or other materials provided with the distribution. | 1475 | * documentation and/or other materials provided with the distribution. | |
1476 | * 3. All advertising materials mentioning features or use of this software | |||
1477 | * must display the following acknowledgement: | |||
1478 | * This product includes software developed by Manuel Bouyer. | |||
1479 | * 4. The name of the author may not be used to endorse or promote products | |||
1480 | * derived from this software without specific prior written permission. | |||
1481 | * | 1476 | * | |
1482 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 1477 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
1483 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 1478 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
1484 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 1479 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
1485 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 1480 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
1486 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 1481 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
1487 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 1482 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
1488 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 1483 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
1489 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 1484 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
1490 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 1485 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
1491 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 1486 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
1492 | */ | 1487 | */ | |
1493 | 1488 | |||
1494 | /*- | 1489 | /*- | |
1495 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | 1490 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | |
1496 | * All rights reserved. | 1491 | * All rights reserved. | |
1497 | * | 1492 | * | |
1498 | * This code is derived from software contributed to The NetBSD Foundation | 1493 | * This code is derived from software contributed to The NetBSD Foundation | |
1499 | * by Charles M. Hannum and by Onno van der Linden. | 1494 | * by Charles M. Hannum and by Onno van der Linden. | |
1500 | * | 1495 | * | |
1501 | * Redistribution and use in source and binary forms, with or without | 1496 | * Redistribution and use in source and binary forms, with or without | |
1502 | * modification, are permitted provided that the following conditions | 1497 | * modification, are permitted provided that the following conditions | |
1503 | * are met: | 1498 | * are met: | |
1504 | * 1. Redistributions of source code must retain the above copyright | 1499 | * 1. Redistributions of source code must retain the above copyright | |
1505 | * notice, this list of conditions and the following disclaimer. | 1500 | * notice, this list of conditions and the following disclaimer. | |
1506 | * 2. Redistributions in binary form must reproduce the above copyright | 1501 | * 2. Redistributions in binary form must reproduce the above copyright | |
1507 | * notice, this list of conditions and the following disclaimer in the | 1502 | * notice, this list of conditions and the following disclaimer in the | |
1508 | * documentation and/or other materials provided with the distribution. | 1503 | * documentation and/or other materials provided with the distribution. | |
1509 | * 3. All advertising materials mentioning features or use of this software | 1504 | * 3. All advertising materials mentioning features or use of this software | |
1510 | * must display the following acknowledgement: | 1505 | * must display the following acknowledgement: | |
1511 | * This product includes software developed by the NetBSD | 1506 | * This product includes software developed by the NetBSD | |
1512 | * Foundation, Inc. and its contributors. | 1507 | * Foundation, Inc. and its contributors. | |
1513 | * 4. Neither the name of The NetBSD Foundation nor the names of its | 1508 | * 4. Neither the name of The NetBSD Foundation nor the names of its | |
1514 | * contributors may be used to endorse or promote products derived | 1509 | * contributors may be used to endorse or promote products derived | |
1515 | * from this software without specific prior written permission. | 1510 | * from this software without specific prior written permission. | |
1516 | * | 1511 | * | |
1517 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 1512 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
1518 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 1513 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
1519 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 1514 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
1520 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 1515 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
1521 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 1516 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
1522 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 1517 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
1523 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 1518 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
1524 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 1519 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
1525 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 1520 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
1526 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 1521 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
1527 | * POSSIBILITY OF SUCH DAMAGE. | 1522 | * POSSIBILITY OF SUCH DAMAGE. | |
1528 | */ | 1523 | */ | |
1529 | 1524 | |||
1530 | static const char ST506[] = "ST506"; | 1525 | static const char ST506[] = "ST506"; | |
1531 | 1526 | |||
1532 | #define ACEIORETRIES_SINGLE 4 /* number of retries before single-sector */ | 1527 | #define ACEIORETRIES_SINGLE 4 /* number of retries before single-sector */ | |
1533 | #define ACEIORETRIES 5 /* number of retries before giving up */ | 1528 | #define ACEIORETRIES 5 /* number of retries before giving up */ | |
1534 | #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ | 1529 | #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ | |
1535 | 1530 | |||
1536 | #define ACEUNIT(dev) DISKUNIT(dev) | 1531 | #define ACEUNIT(dev) DISKUNIT(dev) | |
1537 | #define ACEPART(dev) DISKPART(dev) | 1532 | #define ACEPART(dev) DISKPART(dev) | |
1538 | #define ACEMINOR(unit, part) DISKMINOR(unit, part) | 1533 | #define ACEMINOR(unit, part) DISKMINOR(unit, part) | |
1539 | #define MAKEACEDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) | 1534 | #define MAKEACEDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) | |
1540 | 1535 | |||
1541 | #define ACELABELDEV(dev) (MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART)) | 1536 | #define ACELABELDEV(dev) (MAKEACEDEV(major(dev), ACEUNIT(dev), RAW_PART)) | |
1542 | 1537 | |||
1543 | void aceperror(const struct ace_softc *); | 1538 | void aceperror(const struct ace_softc *); | |
1544 | 1539 | |||
1545 | extern struct cfdriver ace_cd; | 1540 | extern struct cfdriver ace_cd; | |
1546 | 1541 | |||
1547 | dev_type_open(aceopen); | 1542 | dev_type_open(aceopen); | |
1548 | dev_type_close(aceclose); | 1543 | dev_type_close(aceclose); | |
1549 | dev_type_read(aceread); | 1544 | dev_type_read(aceread); | |
1550 | dev_type_write(acewrite); | 1545 | dev_type_write(acewrite); | |
1551 | dev_type_ioctl(aceioctl); | 1546 | dev_type_ioctl(aceioctl); | |
1552 | dev_type_strategy(acestrategy); | 1547 | dev_type_strategy(acestrategy); | |
1553 | dev_type_dump(acedump); | 1548 | dev_type_dump(acedump); | |
1554 | dev_type_size(acesize); | 1549 | dev_type_size(acesize); | |
1555 | 1550 | |||
1556 | const struct bdevsw ace_bdevsw = { | 1551 | const struct bdevsw ace_bdevsw = { | |
1557 | .d_open = aceopen, | 1552 | .d_open = aceopen, | |
1558 | .d_close = aceclose, | 1553 | .d_close = aceclose, | |
1559 | .d_strategy = acestrategy, | 1554 | .d_strategy = acestrategy, | |
1560 | .d_ioctl = aceioctl, | 1555 | .d_ioctl = aceioctl, | |
1561 | .d_dump = acedump, | 1556 | .d_dump = acedump, | |
1562 | .d_psize = acesize, | 1557 | .d_psize = acesize, | |
1563 | .d_discard = nodiscard, | 1558 | .d_discard = nodiscard, | |
1564 | .d_flag = D_DISK | 1559 | .d_flag = D_DISK | |
1565 | }; | 1560 | }; | |
1566 | 1561 | |||
1567 | const struct cdevsw ace_cdevsw = { | 1562 | const struct cdevsw ace_cdevsw = { | |
1568 | .d_open = aceopen, | 1563 | .d_open = aceopen, | |
1569 | .d_close = aceclose, | 1564 | .d_close = aceclose, | |
1570 | .d_read = aceread, | 1565 | .d_read = aceread, | |
1571 | .d_write = acewrite, | 1566 | .d_write = acewrite, | |
1572 | .d_ioctl = aceioctl, | 1567 | .d_ioctl = aceioctl, | |
1573 | .d_stop = nostop, | 1568 | .d_stop = nostop, | |
1574 | .d_tty = notty, | 1569 | .d_tty = notty, | |
1575 | .d_poll = nopoll, | 1570 | .d_poll = nopoll, | |
1576 | .d_mmap = nommap, | 1571 | .d_mmap = nommap, | |
1577 | .d_kqfilter = nokqfilter, | 1572 | .d_kqfilter = nokqfilter, | |
1578 | .d_discard = nodiscard, | 1573 | .d_discard = nodiscard, | |
1579 | .d_flag = D_DISK | 1574 | .d_flag = D_DISK | |
1580 | }; | 1575 | }; | |
1581 | 1576 | |||
1582 | void acegetdefaultlabel(struct ace_softc *, struct disklabel *); | 1577 | void acegetdefaultlabel(struct ace_softc *, struct disklabel *); | |
1583 | void acegetdisklabel(struct ace_softc *); | 1578 | void acegetdisklabel(struct ace_softc *); | |
1584 | void acestart(void *); | 1579 | void acestart(void *); | |
1585 | void __acestart(struct ace_softc*, struct buf *); | 1580 | void __acestart(struct ace_softc*, struct buf *); | |
1586 | void acerestart(void *); | 1581 | void acerestart(void *); | |
1587 | 1582 | |||
1588 | struct dkdriver acedkdriver = { | 1583 | struct dkdriver acedkdriver = { | |
1589 | .d_strategy = acestrategy, | 1584 | .d_strategy = acestrategy, | |
1590 | .d_minphys = minphys | 1585 | .d_minphys = minphys | |
1591 | }; | 1586 | }; | |
1592 | 1587 | |||
1593 | #ifdef HAS_BAD144_HANDLING | 1588 | #ifdef HAS_BAD144_HANDLING | |
1594 | static void bad144intern(struct ace_softc *); | 1589 | static void bad144intern(struct ace_softc *); | |
1595 | #endif | 1590 | #endif | |
1596 | 1591 | |||
1597 | void | 1592 | void | |
1598 | aceattach(struct ace_softc *ace) | 1593 | aceattach(struct ace_softc *ace) | |
1599 | { | 1594 | { | |
1600 | device_t self = ace->sc_dev; | 1595 | device_t self = ace->sc_dev; | |
1601 | char tbuf[41], pbuf[9], c, *p, *q; | 1596 | char tbuf[41], pbuf[9], c, *p, *q; | |
1602 | int i, blank; | 1597 | int i, blank; | |
1603 | DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE); | 1598 | DEBUG_PRINT(("aceattach\n"), DEBUG_FUNCS | DEBUG_PROBE); | |
1604 | 1599 | |||
1605 | callout_init(&ace->sc_restart_ch, 0); | 1600 | callout_init(&ace->sc_restart_ch, 0); | |
1606 | bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); | 1601 | bufq_alloc(&ace->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); | |
1607 | 1602 | |||
1608 | ace->openings = 1; /* wazziz?*/ | 1603 | ace->openings = 1; /* wazziz?*/ | |
1609 | ace->sc_multi = MAXATATIME; | 1604 | ace->sc_multi = MAXATATIME; | |
1610 | 1605 | |||
1611 | aprint_naive("\n"); | 1606 | aprint_naive("\n"); | |
1612 | 1607 | |||
1613 | /* setup all required fields so that if the attach fails we are ok */ | 1608 | /* setup all required fields so that if the attach fails we are ok */ | |
1614 | ace->sc_dk.dk_driver = &acedkdriver; | 1609 | ace->sc_dk.dk_driver = &acedkdriver; | |
1615 | ace->sc_dk.dk_name = device_xname(ace->sc_dev); | 1610 | ace->sc_dk.dk_name = device_xname(ace->sc_dev); | |
1616 | 1611 | |||
1617 | /* read our drive info */ | 1612 | /* read our drive info */ | |
1618 | if (sysace_attach(ace) != 0) { | 1613 | if (sysace_attach(ace) != 0) { | |
1619 | aprint_error_dev(ace->sc_dev, "attach failed\n"); | 1614 | aprint_error_dev(ace->sc_dev, "attach failed\n"); | |
1620 | return; | 1615 | return; | |
1621 | } | 1616 | } | |
1622 | 1617 | |||
1623 | aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n", | 1618 | aprint_normal_dev(ace->sc_dev, "drive supports %d-sector PIO xfers\n", | |
1624 | ace->sc_multi); | 1619 | ace->sc_multi); | |
1625 | 1620 | |||
1626 | for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0; | 1621 | for (blank = 0, p = ace->sc_params.ModelNumber, q = tbuf, i = 0; | |
1627 | i < sizeof(ace->sc_params.ModelNumber); i++) { | 1622 | i < sizeof(ace->sc_params.ModelNumber); i++) { | |
1628 | c = *p++; | 1623 | c = *p++; | |
1629 | if (c == '\0') | 1624 | if (c == '\0') | |
1630 | break; | 1625 | break; | |
1631 | if (c != ' ') { | 1626 | if (c != ' ') { | |
1632 | if (blank) { | 1627 | if (blank) { | |
1633 | *q++ = ' '; | 1628 | *q++ = ' '; | |
1634 | blank = 0; | 1629 | blank = 0; | |
1635 | } | 1630 | } | |
1636 | *q++ = c; | 1631 | *q++ = c; | |
1637 | } else | 1632 | } else | |
1638 | blank = 1; | 1633 | blank = 1; | |
1639 | } | 1634 | } | |
1640 | *q++ = '\0'; | 1635 | *q++ = '\0'; | |
1641 | 1636 | |||
1642 | aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf); | 1637 | aprint_normal_dev(ace->sc_dev, "card is <%s>\n", tbuf); | |
1643 | 1638 | |||
1644 | format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE); | 1639 | format_bytes(pbuf, sizeof(pbuf), ace->sc_capacity * DEV_BSIZE); | |
1645 | aprint_normal("%s: %s, %d cyl, %d head, %d sec, " | 1640 | aprint_normal("%s: %s, %d cyl, %d head, %d sec, " | |
1646 | "%d bytes/sect x %llu sectors\n", | 1641 | "%d bytes/sect x %llu sectors\n", | |
1647 | device_xname(self), pbuf, | 1642 | device_xname(self), pbuf, | |
1648 | (int)(ace->sc_capacity / | 1643 | (int)(ace->sc_capacity / | |
1649 | (ace->sc_params.CurrentNumberOfHeads * | 1644 | (ace->sc_params.CurrentNumberOfHeads * | |
1650 | ace->sc_params.CurrentSectorsPerTrack)), | 1645 | ace->sc_params.CurrentSectorsPerTrack)), | |
1651 | ace->sc_params.CurrentNumberOfHeads, | 1646 | ace->sc_params.CurrentNumberOfHeads, | |
1652 | ace->sc_params.CurrentSectorsPerTrack, | 1647 | ace->sc_params.CurrentSectorsPerTrack, | |
1653 | DEV_BSIZE, (unsigned long long)ace->sc_capacity); | 1648 | DEV_BSIZE, (unsigned long long)ace->sc_capacity); | |
1654 | 1649 | |||
1655 | /* | 1650 | /* | |
1656 | * Attach the disk structure. We fill in dk_info later. | 1651 | * Attach the disk structure. We fill in dk_info later. | |
1657 | */ | 1652 | */ | |
1658 | disk_attach(&ace->sc_dk); | 1653 | disk_attach(&ace->sc_dk); | |
1659 | 1654 | |||
1660 | rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev), | 1655 | rnd_attach_source(&ace->rnd_source, device_xname(ace->sc_dev), | |
1661 | RND_TYPE_DISK, RND_FLAG_DEFAULT); | 1656 | RND_TYPE_DISK, RND_FLAG_DEFAULT); | |
1662 | 1657 | |||
1663 | } | 1658 | } | |
1664 | 1659 | |||
1665 | int | 1660 | int | |
1666 | aceactivate(device_t self, enum devact act) | 1661 | aceactivate(device_t self, enum devact act) | |
1667 | { | 1662 | { | |
1668 | int rv = 0; | 1663 | int rv = 0; | |
1669 | 1664 | |||
1670 | switch (act) { | 1665 | switch (act) { | |
1671 | case DVACT_DEACTIVATE: | 1666 | case DVACT_DEACTIVATE: | |
1672 | /* | 1667 | /* | |
1673 | * Nothing to do; we key off the device's DVF_ACTIVATE. | 1668 | * Nothing to do; we key off the device's DVF_ACTIVATE. | |
1674 | */ | 1669 | */ | |
1675 | break; | 1670 | break; | |
1676 | default: | 1671 | default: | |
1677 | rv = EOPNOTSUPP; | 1672 | rv = EOPNOTSUPP; | |
1678 | } | 1673 | } | |
1679 | return rv; | 1674 | return rv; | |
1680 | } | 1675 | } | |
1681 | 1676 | |||
1682 | int | 1677 | int | |
1683 | acedetach(device_t self, int flags) | 1678 | acedetach(device_t self, int flags) | |
1684 | { | 1679 | { | |
1685 | struct ace_softc *sc = device_private(self); | 1680 | struct ace_softc *sc = device_private(self); | |
1686 | int s, bmaj, cmaj, i, mn; | 1681 | int s, bmaj, cmaj, i, mn; | |
1687 | 1682 | |||
1688 | /* locate the major number */ | 1683 | /* locate the major number */ | |
1689 | bmaj = bdevsw_lookup_major(&ace_bdevsw); | 1684 | bmaj = bdevsw_lookup_major(&ace_bdevsw); | |
1690 | cmaj = cdevsw_lookup_major(&ace_cdevsw); | 1685 | cmaj = cdevsw_lookup_major(&ace_cdevsw); | |
1691 | 1686 | |||
1692 | /* Nuke the vnodes for any open instances. */ | 1687 | /* Nuke the vnodes for any open instances. */ | |
1693 | for (i = 0; i < MAXPARTITIONS; i++) { | 1688 | for (i = 0; i < MAXPARTITIONS; i++) { | |
1694 | mn = ACEMINOR(device_unit(self), i); | 1689 | mn = ACEMINOR(device_unit(self), i); | |
1695 | vdevgone(bmaj, mn, mn, VBLK); | 1690 | vdevgone(bmaj, mn, mn, VBLK); | |
1696 | vdevgone(cmaj, mn, mn, VCHR); | 1691 | vdevgone(cmaj, mn, mn, VCHR); | |
1697 | } | 1692 | } | |
1698 | 1693 | |||
1699 | /* Delete all of our wedges. */ | 1694 | /* Delete all of our wedges. */ | |
1700 | dkwedge_delall(&sc->sc_dk); | 1695 | dkwedge_delall(&sc->sc_dk); | |
1701 | 1696 | |||
1702 | s = splbio(); | 1697 | s = splbio(); | |
1703 | 1698 | |||
1704 | /* Kill off any queued buffers. */ | 1699 | /* Kill off any queued buffers. */ | |
1705 | bufq_drain(sc->sc_q); | 1700 | bufq_drain(sc->sc_q); | |
1706 | 1701 | |||
1707 | #if 0 | 1702 | #if 0 | |
1708 | sc->atabus->ata_killpending(sc->drvp); | 1703 | sc->atabus->ata_killpending(sc->drvp); | |
1709 | #endif | 1704 | #endif | |
1710 | 1705 | |||
1711 | splx(s); | 1706 | splx(s); | |
1712 | bufq_free(sc->sc_q); | 1707 | bufq_free(sc->sc_q); | |
1713 | 1708 | |||
1714 | /* Detach disk. */ | 1709 | /* Detach disk. */ | |
1715 | disk_detach(&sc->sc_dk); | 1710 | disk_detach(&sc->sc_dk); | |
1716 | 1711 | |||
1717 | /* Unhook the entropy source. */ | 1712 | /* Unhook the entropy source. */ | |
1718 | rnd_detach_source(&sc->rnd_source); | 1713 | rnd_detach_source(&sc->rnd_source); | |
1719 | 1714 | |||
1720 | #if 0 | 1715 | #if 0 | |
1721 | sc->drvp->drive_flags = 0; /* no drive any more here */ | 1716 | sc->drvp->drive_flags = 0; /* no drive any more here */ | |
1722 | #endif | 1717 | #endif | |
1723 | 1718 | |||
1724 | return 0; | 1719 | return 0; | |
1725 | } | 1720 | } | |
1726 | 1721 | |||
1727 | /* | 1722 | /* | |
1728 | * Read/write routine for a buffer. Validates the arguments and schedules the | 1723 | * Read/write routine for a buffer. Validates the arguments and schedules the | |
1729 | * transfer. Does not wait for the transfer to complete. | 1724 | * transfer. Does not wait for the transfer to complete. | |
1730 | */ | 1725 | */ | |
1731 | void | 1726 | void | |
1732 | acestrategy(struct buf *bp) | 1727 | acestrategy(struct buf *bp) | |
1733 | { | 1728 | { | |
1734 | struct ace_softc *ace; | 1729 | struct ace_softc *ace; | |
1735 | struct disklabel *lp; | 1730 | struct disklabel *lp; | |
1736 | daddr_t blkno; | 1731 | daddr_t blkno; | |
1737 | int s; | 1732 | int s; | |
1738 | 1733 | |||
1739 | ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev)); | 1734 | ace = device_lookup_private(&ace_cd, ACEUNIT(bp->b_dev)); | |
1740 | 1735 | |||
1741 | if (ace == NULL) { | 1736 | if (ace == NULL) { | |
1742 | bp->b_error = ENXIO; | 1737 | bp->b_error = ENXIO; | |
1743 | biodone(bp); | 1738 | biodone(bp); | |
1744 | return; | 1739 | return; | |
1745 | } | 1740 | } | |
1746 | lp = ace->sc_dk.dk_label; | 1741 | lp = ace->sc_dk.dk_label; | |
1747 | 1742 | |||
1748 | DEBUG_PRINT(("acestrategy (%s) %lld\n", | 1743 | DEBUG_PRINT(("acestrategy (%s) %lld\n", | |
1749 | device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS); | 1744 | device_xname(ace->sc_dev), bp->b_blkno), DEBUG_XFERS); | |
1750 | 1745 | |||
1751 | /* Valid request? */ | 1746 | /* Valid request? */ | |
1752 | if (bp->b_blkno < 0 || | 1747 | if (bp->b_blkno < 0 || | |
1753 | (bp->b_bcount % lp->d_secsize) != 0 || | 1748 | (bp->b_bcount % lp->d_secsize) != 0 || | |
1754 | (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { | 1749 | (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { | |
1755 | bp->b_error = EINVAL; | 1750 | bp->b_error = EINVAL; | |
1756 | goto done; | 1751 | goto done; | |
1757 | } | 1752 | } | |
1758 | 1753 | |||
1759 | /* If device invalidated (e.g. media change, door open), error. */ | 1754 | /* If device invalidated (e.g. media change, door open), error. */ | |
1760 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | 1755 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | |
1761 | bp->b_error = EIO; | 1756 | bp->b_error = EIO; | |
1762 | goto done; | 1757 | goto done; | |
1763 | } | 1758 | } | |
1764 | 1759 | |||
1765 | /* If it's a null transfer, return immediately. */ | 1760 | /* If it's a null transfer, return immediately. */ | |
1766 | if (bp->b_bcount == 0) | 1761 | if (bp->b_bcount == 0) | |
1767 | goto done; | 1762 | goto done; | |
1768 | 1763 | |||
1769 | /* | 1764 | /* | |
1770 | * Do bounds checking, adjust transfer. if error, process. | 1765 | * Do bounds checking, adjust transfer. if error, process. | |
1771 | * If end of partition, just return. | 1766 | * If end of partition, just return. | |
1772 | */ | 1767 | */ | |
1773 | if (ACEPART(bp->b_dev) == RAW_PART) { | 1768 | if (ACEPART(bp->b_dev) == RAW_PART) { | |
1774 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, | 1769 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, | |
1775 | ace->sc_capacity) <= 0) | 1770 | ace->sc_capacity) <= 0) | |
1776 | goto done; | 1771 | goto done; | |
1777 | } else { | 1772 | } else { | |
1778 | if (bounds_check_with_label(&ace->sc_dk, bp, | 1773 | if (bounds_check_with_label(&ace->sc_dk, bp, | |
1779 | (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0) | 1774 | (ace->sc_flags & (ACEF_WLABEL|ACEF_LABELLING)) != 0) <= 0) | |
1780 | goto done; | 1775 | goto done; | |
1781 | } | 1776 | } | |
1782 | 1777 | |||
1783 | /* | 1778 | /* | |
1784 | * Now convert the block number to absolute and put it in | 1779 | * Now convert the block number to absolute and put it in | |
1785 | * terms of the device's logical block size. | 1780 | * terms of the device's logical block size. | |
1786 | */ | 1781 | */ | |
1787 | if (lp->d_secsize >= DEV_BSIZE) | 1782 | if (lp->d_secsize >= DEV_BSIZE) | |
1788 | blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); | 1783 | blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); | |
1789 | else | 1784 | else | |
1790 | blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); | 1785 | blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); | |
1791 | 1786 | |||
1792 | if (ACEPART(bp->b_dev) != RAW_PART) | 1787 | if (ACEPART(bp->b_dev) != RAW_PART) | |
1793 | blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset; | 1788 | blkno += lp->d_partitions[ACEPART(bp->b_dev)].p_offset; | |
1794 | 1789 | |||
1795 | bp->b_rawblkno = blkno; | 1790 | bp->b_rawblkno = blkno; | |
1796 | 1791 | |||
1797 | /* Queue transfer on drive, activate drive and controller if idle. */ | 1792 | /* Queue transfer on drive, activate drive and controller if idle. */ | |
1798 | s = splbio(); | 1793 | s = splbio(); | |
1799 | bufq_put(ace->sc_q, bp); | 1794 | bufq_put(ace->sc_q, bp); | |
1800 | acestart(ace); | 1795 | acestart(ace); | |
1801 | splx(s); | 1796 | splx(s); | |
1802 | return; | 1797 | return; | |
1803 | done: | 1798 | done: | |
1804 | /* Toss transfer; we're done early. */ | 1799 | /* Toss transfer; we're done early. */ | |
1805 | bp->b_resid = bp->b_bcount; | 1800 | bp->b_resid = bp->b_bcount; | |
1806 | biodone(bp); | 1801 | biodone(bp); | |
1807 | } | 1802 | } | |
1808 | 1803 | |||
1809 | /* | 1804 | /* | |
1810 | * Queue a drive for I/O. | 1805 | * Queue a drive for I/O. | |
1811 | */ | 1806 | */ | |
1812 | void | 1807 | void | |
1813 | acestart(void *arg) | 1808 | acestart(void *arg) | |
1814 | { | 1809 | { | |
1815 | struct ace_softc *ace = arg; | 1810 | struct ace_softc *ace = arg; | |
1816 | struct buf *bp = NULL; | 1811 | struct buf *bp = NULL; | |
1817 | 1812 | |||
1818 | DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); | 1813 | DEBUG_PRINT(("acestart %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); | |
1819 | while (ace->openings > 0) { | 1814 | while (ace->openings > 0) { | |
1820 | 1815 | |||
1821 | /* Is there a buf for us ? */ | 1816 | /* Is there a buf for us ? */ | |
1822 | if ((bp = bufq_get(ace->sc_q)) == NULL) | 1817 | if ((bp = bufq_get(ace->sc_q)) == NULL) | |
1823 | return; | 1818 | return; | |
1824 | 1819 | |||
1825 | /* | 1820 | /* | |
1826 | * Make the command. First lock the device | 1821 | * Make the command. First lock the device | |
1827 | */ | 1822 | */ | |
1828 | ace->openings--; | 1823 | ace->openings--; | |
1829 | 1824 | |||
1830 | ace->retries = 0; | 1825 | ace->retries = 0; | |
1831 | __acestart(ace, bp); | 1826 | __acestart(ace, bp); | |
1832 | } | 1827 | } | |
1833 | } | 1828 | } | |
1834 | 1829 | |||
1835 | void | 1830 | void | |
1836 | __acestart(struct ace_softc *sc, struct buf *bp) | 1831 | __acestart(struct ace_softc *sc, struct buf *bp) | |
1837 | { | 1832 | { | |
1838 | 1833 | |||
1839 | sc->sc_bp = bp; | 1834 | sc->sc_bp = bp; | |
1840 | /* | 1835 | /* | |
1841 | * If we're retrying, retry in single-sector mode. This will give us | 1836 | * If we're retrying, retry in single-sector mode. This will give us | |
1842 | * the sector number of the problem, and will eventually allow the | 1837 | * the sector number of the problem, and will eventually allow the | |
1843 | * transfer to succeed. | 1838 | * transfer to succeed. | |
1844 | */ | 1839 | */ | |
1845 | if (sc->retries >= ACEIORETRIES_SINGLE) | 1840 | if (sc->retries >= ACEIORETRIES_SINGLE) | |
1846 | sc->sc_bio.flags = ATA_SINGLE; | 1841 | sc->sc_bio.flags = ATA_SINGLE; | |
1847 | else | 1842 | else | |
1848 | sc->sc_bio.flags = 0; | 1843 | sc->sc_bio.flags = 0; | |
1849 | if (bp->b_flags & B_READ) | 1844 | if (bp->b_flags & B_READ) | |
1850 | sc->sc_bio.flags |= ATA_READ; | 1845 | sc->sc_bio.flags |= ATA_READ; | |
1851 | sc->sc_bio.blkno = bp->b_rawblkno; | 1846 | sc->sc_bio.blkno = bp->b_rawblkno; | |
1852 | sc->sc_bio.blkdone = 0; | 1847 | sc->sc_bio.blkdone = 0; | |
1853 | sc->sc_bio.nbytes = bp->b_bcount; | 1848 | sc->sc_bio.nbytes = bp->b_bcount; | |
1854 | sc->sc_bio.nblks = bp->b_bcount >> CF_SECBITS; | 1849 | sc->sc_bio.nblks = bp->b_bcount >> CF_SECBITS; | |
1855 | sc->sc_bio.databuf = bp->b_data; | 1850 | sc->sc_bio.databuf = bp->b_data; | |
1856 | /* Instrumentation. */ | 1851 | /* Instrumentation. */ | |
1857 | disk_busy(&sc->sc_dk); | 1852 | disk_busy(&sc->sc_dk); | |
1858 | sc->active_xfer = bp; | 1853 | sc->active_xfer = bp; | |
1859 | wakeup(&sc->ch_thread); | 1854 | wakeup(&sc->ch_thread); | |
1860 | } | 1855 | } | |
1861 | 1856 | |||
1862 | void | 1857 | void | |
1863 | acedone(struct ace_softc *ace) | 1858 | acedone(struct ace_softc *ace) | |
1864 | { | 1859 | { | |
1865 | struct buf *bp = ace->sc_bp; | 1860 | struct buf *bp = ace->sc_bp; | |
1866 | const char *errmsg; | 1861 | const char *errmsg; | |
1867 | int do_perror = 0; | 1862 | int do_perror = 0; | |
1868 | 1863 | |||
1869 | DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); | 1864 | DEBUG_PRINT(("acedone %s\n", device_xname(ace->sc_dev)), DEBUG_XFERS); | |
1870 | 1865 | |||
1871 | if (bp == NULL) | 1866 | if (bp == NULL) | |
1872 | return; | 1867 | return; | |
1873 | 1868 | |||
1874 | bp->b_resid = ace->sc_bio.nbytes; | 1869 | bp->b_resid = ace->sc_bio.nbytes; | |
1875 | switch (ace->sc_bio.error) { | 1870 | switch (ace->sc_bio.error) { | |
1876 | case ETIMEDOUT: | 1871 | case ETIMEDOUT: | |
1877 | errmsg = "device timeout"; | 1872 | errmsg = "device timeout"; | |
1878 | do_perror = 1; | 1873 | do_perror = 1; | |
1879 | goto retry; | 1874 | goto retry; | |
1880 | case EBUSY: | 1875 | case EBUSY: | |
1881 | case EDOOFUS: | 1876 | case EDOOFUS: | |
1882 | errmsg = "device stuck"; | 1877 | errmsg = "device stuck"; | |
1883 | retry: /* Just reset and retry. Can we do more ? */ | 1878 | retry: /* Just reset and retry. Can we do more ? */ | |
1884 | sysace_reset(ace); | 1879 | sysace_reset(ace); | |
1885 | diskerr(bp, "ace", errmsg, LOG_PRINTF, | 1880 | diskerr(bp, "ace", errmsg, LOG_PRINTF, | |
1886 | ace->sc_bio.blkdone, ace->sc_dk.dk_label); | 1881 | ace->sc_bio.blkdone, ace->sc_dk.dk_label); | |
1887 | if (ace->retries < ACEIORETRIES) | 1882 | if (ace->retries < ACEIORETRIES) | |
1888 | printf(", retrying"); | 1883 | printf(", retrying"); | |
1889 | printf("\n"); | 1884 | printf("\n"); | |
1890 | if (do_perror) | 1885 | if (do_perror) | |
1891 | aceperror(ace); | 1886 | aceperror(ace); | |
1892 | if (ace->retries < ACEIORETRIES) { | 1887 | if (ace->retries < ACEIORETRIES) { | |
1893 | ace->retries++; | 1888 | ace->retries++; | |
1894 | callout_reset(&ace->sc_restart_ch, RECOVERYTIME, | 1889 | callout_reset(&ace->sc_restart_ch, RECOVERYTIME, | |
1895 | acerestart, ace); | 1890 | acerestart, ace); | |
1896 | return; | 1891 | return; | |
1897 | } | 1892 | } | |
1898 | 1893 | |||
1899 | bp->b_error = EIO; | 1894 | bp->b_error = EIO; | |
1900 | break; | 1895 | break; | |
1901 | case 0: | 1896 | case 0: | |
1902 | if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0) | 1897 | if ((ace->sc_bio.flags & ATA_CORR) || ace->retries > 0) | |
1903 | printf("%s: soft error (corrected)\n", | 1898 | printf("%s: soft error (corrected)\n", | |
1904 | device_xname(ace->sc_dev)); | 1899 | device_xname(ace->sc_dev)); | |
1905 | break; | 1900 | break; | |
1906 | case ENODEV: | 1901 | case ENODEV: | |
1907 | case E2BIG: | 1902 | case E2BIG: | |
1908 | bp->b_error = EIO; | 1903 | bp->b_error = EIO; | |
1909 | break; | 1904 | break; | |
1910 | } | 1905 | } | |
1911 | disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid), | 1906 | disk_unbusy(&ace->sc_dk, (bp->b_bcount - bp->b_resid), | |
1912 | (bp->b_flags & B_READ)); | 1907 | (bp->b_flags & B_READ)); | |
1913 | rnd_add_uint32(&ace->rnd_source, bp->b_blkno); | 1908 | rnd_add_uint32(&ace->rnd_source, bp->b_blkno); | |
1914 | biodone(bp); | 1909 | biodone(bp); | |
1915 | ace->openings++; | 1910 | ace->openings++; | |
1916 | acestart(ace); | 1911 | acestart(ace); | |
1917 | } | 1912 | } | |
1918 | 1913 | |||
1919 | void | 1914 | void | |
1920 | acerestart(void *v) | 1915 | acerestart(void *v) | |
1921 | { | 1916 | { | |
1922 | struct ace_softc *ace = v; | 1917 | struct ace_softc *ace = v; | |
1923 | struct buf *bp = ace->sc_bp; | 1918 | struct buf *bp = ace->sc_bp; | |
1924 | int s; | 1919 | int s; | |
1925 | DEBUG_PRINT(("acerestart %s\n", | 1920 | DEBUG_PRINT(("acerestart %s\n", | |
1926 | device_xname(ace->sc_dev)), DEBUG_XFERS); | 1921 | device_xname(ace->sc_dev)), DEBUG_XFERS); | |
1927 | 1922 | |||
1928 | s = splbio(); | 1923 | s = splbio(); | |
1929 | __acestart(v, bp); | 1924 | __acestart(v, bp); | |
1930 | splx(s); | 1925 | splx(s); | |
1931 | } | 1926 | } | |
1932 | 1927 | |||
1933 | int | 1928 | int | |
1934 | aceread(dev_t dev, struct uio *uio, int flags) | 1929 | aceread(dev_t dev, struct uio *uio, int flags) | |
1935 | { | 1930 | { | |
1936 | int r; | 1931 | int r; | |
1937 | 1932 | |||
1938 | DEBUG_PRINT(("aceread\n"), DEBUG_XFERS); | 1933 | DEBUG_PRINT(("aceread\n"), DEBUG_XFERS); | |
1939 | r = physio(acestrategy, NULL, dev, B_READ, minphys, uio); | 1934 | r = physio(acestrategy, NULL, dev, B_READ, minphys, uio); | |
1940 | DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS); | 1935 | DEBUG_PRINT(("aceread -> x%x resid=%x\n",r,uio->uio_resid),DEBUG_XFERS); | |
1941 | 1936 | |||
1942 | return r; | 1937 | return r; | |
1943 | } | 1938 | } | |
1944 | 1939 | |||
1945 | int | 1940 | int | |
1946 | acewrite(dev_t dev, struct uio *uio, int flags) | 1941 | acewrite(dev_t dev, struct uio *uio, int flags) | |
1947 | { | 1942 | { | |
1948 | 1943 | |||
1949 | DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS); | 1944 | DEBUG_PRINT(("acewrite\n"), DEBUG_XFERS); | |
1950 | return physio(acestrategy, NULL, dev, B_WRITE, minphys, uio); | 1945 | return physio(acestrategy, NULL, dev, B_WRITE, minphys, uio); | |
1951 | } | 1946 | } | |
1952 | 1947 | |||
1953 | int | 1948 | int | |
1954 | aceopen(dev_t dev, int flag, int fmt, struct lwp *l) | 1949 | aceopen(dev_t dev, int flag, int fmt, struct lwp *l) | |
1955 | { | 1950 | { | |
1956 | struct ace_softc *ace; | 1951 | struct ace_softc *ace; | |
1957 | int part, error; | 1952 | int part, error; | |
1958 | 1953 | |||
1959 | DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS); | 1954 | DEBUG_PRINT(("aceopen\n"), DEBUG_FUNCS); | |
1960 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | 1955 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | |
1961 | if (ace == NULL) | 1956 | if (ace == NULL) | |
1962 | return ENXIO; | 1957 | return ENXIO; | |
1963 | 1958 | |||
1964 | if (! device_is_active(ace->sc_dev)) | 1959 | if (! device_is_active(ace->sc_dev)) | |
1965 | return ENODEV; | 1960 | return ENODEV; | |
1966 | 1961 | |||
1967 | part = ACEPART(dev); | 1962 | part = ACEPART(dev); | |
1968 | 1963 | |||
1969 | mutex_enter(&ace->sc_dk.dk_openlock); | 1964 | mutex_enter(&ace->sc_dk.dk_openlock); | |
1970 | 1965 | |||
1971 | /* | 1966 | /* | |
1972 | * If there are wedges, and this is not RAW_PART, then we | 1967 | * If there are wedges, and this is not RAW_PART, then we | |
1973 | * need to fail. | 1968 | * need to fail. | |
1974 | */ | 1969 | */ | |
1975 | if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) { | 1970 | if (ace->sc_dk.dk_nwedges != 0 && part != RAW_PART) { | |
1976 | error = EBUSY; | 1971 | error = EBUSY; | |
1977 | goto bad; | 1972 | goto bad; | |
1978 | } | 1973 | } | |
1979 | 1974 | |||
1980 | if (ace->sc_dk.dk_openmask != 0) { | 1975 | if (ace->sc_dk.dk_openmask != 0) { | |
1981 | /* | 1976 | /* | |
1982 | * If any partition is open, but the disk has been invalidated, | 1977 | * If any partition is open, but the disk has been invalidated, | |
1983 | * disallow further opens. | 1978 | * disallow further opens. | |
1984 | */ | 1979 | */ | |
1985 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | 1980 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | |
1986 | error = EIO; | 1981 | error = EIO; | |
1987 | goto bad; | 1982 | goto bad; | |
1988 | } | 1983 | } | |
1989 | } else { | 1984 | } else { | |
1990 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | 1985 | if ((ace->sc_flags & ACEF_LOADED) == 0) { | |
1991 | ace->sc_flags |= ACEF_LOADED; | 1986 | ace->sc_flags |= ACEF_LOADED; | |
1992 | 1987 | |||
1993 | /* Load the physical device parameters. */ | 1988 | /* Load the physical device parameters. */ | |
1994 | if (ace->sc_capacity == 0) { | 1989 | if (ace->sc_capacity == 0) { | |
1995 | error = sysace_identify(ace); | 1990 | error = sysace_identify(ace); | |
1996 | if (error) | 1991 | if (error) | |
1997 | goto bad; | 1992 | goto bad; | |
1998 | } | 1993 | } | |
1999 | 1994 | |||
2000 | /* Load the partition info if not already loaded. */ | 1995 | /* Load the partition info if not already loaded. */ | |
2001 | acegetdisklabel(ace); | 1996 | acegetdisklabel(ace); | |
2002 | } | 1997 | } | |
2003 | } | 1998 | } | |
2004 | 1999 | |||
2005 | /* Check that the partition exists. */ | 2000 | /* Check that the partition exists. */ | |
2006 | if (part != RAW_PART && | 2001 | if (part != RAW_PART && | |
2007 | (part >= ace->sc_dk.dk_label->d_npartitions || | 2002 | (part >= ace->sc_dk.dk_label->d_npartitions || | |
2008 | ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { | 2003 | ace->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { | |
2009 | error = ENXIO; | 2004 | error = ENXIO; | |
2010 | goto bad; | 2005 | goto bad; | |
2011 | } | 2006 | } | |
2012 | 2007 | |||
2013 | /* Insure only one open at a time. */ | 2008 | /* Insure only one open at a time. */ | |
2014 | switch (fmt) { | 2009 | switch (fmt) { | |
2015 | case S_IFCHR: | 2010 | case S_IFCHR: | |
2016 | ace->sc_dk.dk_copenmask |= (1 << part); | 2011 | ace->sc_dk.dk_copenmask |= (1 << part); | |
2017 | break; | 2012 | break; | |
2018 | case S_IFBLK: | 2013 | case S_IFBLK: | |
2019 | ace->sc_dk.dk_bopenmask |= (1 << part); | 2014 | ace->sc_dk.dk_bopenmask |= (1 << part); | |
2020 | break; | 2015 | break; | |
2021 | } | 2016 | } | |
2022 | ace->sc_dk.dk_openmask = | 2017 | ace->sc_dk.dk_openmask = | |
2023 | ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; | 2018 | ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; | |
2024 | 2019 | |||
2025 | mutex_exit(&ace->sc_dk.dk_openlock); | 2020 | mutex_exit(&ace->sc_dk.dk_openlock); | |
2026 | return 0; | 2021 | return 0; | |
2027 | 2022 | |||
2028 | bad: | 2023 | bad: | |
2029 | mutex_exit(&ace->sc_dk.dk_openlock); | 2024 | mutex_exit(&ace->sc_dk.dk_openlock); | |
2030 | return error; | 2025 | return error; | |
2031 | } | 2026 | } | |
2032 | 2027 | |||
2033 | int | 2028 | int | |
2034 | aceclose(dev_t dev, int flag, int fmt, struct lwp *l) | 2029 | aceclose(dev_t dev, int flag, int fmt, struct lwp *l) | |
2035 | { | 2030 | { | |
2036 | struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | 2031 | struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | |
2037 | int part = ACEPART(dev); | 2032 | int part = ACEPART(dev); | |
2038 | 2033 | |||
2039 | DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS); | 2034 | DEBUG_PRINT(("aceclose\n"), DEBUG_FUNCS); | |
2040 | if (ace == NULL) | 2035 | if (ace == NULL) | |
2041 | return ENXIO; | 2036 | return ENXIO; | |
2042 | 2037 | |||
2043 | mutex_enter(&ace->sc_dk.dk_openlock); | 2038 | mutex_enter(&ace->sc_dk.dk_openlock); | |
2044 | 2039 | |||
2045 | switch (fmt) { | 2040 | switch (fmt) { | |
2046 | case S_IFCHR: | 2041 | case S_IFCHR: | |
2047 | ace->sc_dk.dk_copenmask &= ~(1 << part); | 2042 | ace->sc_dk.dk_copenmask &= ~(1 << part); | |
2048 | break; | 2043 | break; | |
2049 | case S_IFBLK: | 2044 | case S_IFBLK: | |
2050 | ace->sc_dk.dk_bopenmask &= ~(1 << part); | 2045 | ace->sc_dk.dk_bopenmask &= ~(1 << part); | |
2051 | break; | 2046 | break; | |
2052 | } | 2047 | } | |
2053 | ace->sc_dk.dk_openmask = | 2048 | ace->sc_dk.dk_openmask = | |
2054 | ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; | 2049 | ace->sc_dk.dk_copenmask | ace->sc_dk.dk_bopenmask; | |
2055 | 2050 | |||
2056 | if (ace->sc_dk.dk_openmask == 0) { | 2051 | if (ace->sc_dk.dk_openmask == 0) { | |
2057 | 2052 | |||
2058 | if (!(ace->sc_flags & ACEF_KLABEL)) | 2053 | if (!(ace->sc_flags & ACEF_KLABEL)) | |
2059 | ace->sc_flags &= ~ACEF_LOADED; | 2054 | ace->sc_flags &= ~ACEF_LOADED; | |
2060 | 2055 | |||
2061 | } | 2056 | } | |
2062 | 2057 | |||
2063 | mutex_exit(&ace->sc_dk.dk_openlock); | 2058 | mutex_exit(&ace->sc_dk.dk_openlock); | |
2064 | return 0; | 2059 | return 0; | |
2065 | } | 2060 | } | |
2066 | 2061 | |||
2067 | void | 2062 | void | |
2068 | acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp) | 2063 | acegetdefaultlabel(struct ace_softc *ace, struct disklabel *lp) | |
2069 | { | 2064 | { | |
2070 | 2065 | |||
2071 | DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS); | 2066 | DEBUG_PRINT(("acegetdefaultlabel\n"), DEBUG_FUNCS); | |
2072 | memset(lp, 0, sizeof(struct disklabel)); | 2067 | memset(lp, 0, sizeof(struct disklabel)); | |
2073 | 2068 | |||
2074 | lp->d_secsize = DEV_BSIZE; | 2069 | lp->d_secsize = DEV_BSIZE; | |
2075 | lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads; | 2070 | lp->d_ntracks = ace->sc_params.CurrentNumberOfHeads; | |
2076 | lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack; | 2071 | lp->d_nsectors = ace->sc_params.CurrentSectorsPerTrack; | |
2077 | lp->d_ncylinders = ace->sc_capacity / | 2072 | lp->d_ncylinders = ace->sc_capacity / | |
2078 | (ace->sc_params.CurrentNumberOfHeads * | 2073 | (ace->sc_params.CurrentNumberOfHeads * | |
2079 | ace->sc_params.CurrentSectorsPerTrack); | 2074 | ace->sc_params.CurrentSectorsPerTrack); | |
2080 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; | 2075 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; | |
2081 | 2076 | |||
2082 | lp->d_type = DKTYPE_ST506; /* ?!? */ | 2077 | lp->d_type = DKTYPE_ST506; /* ?!? */ | |
2083 | 2078 | |||
2084 | strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16); | 2079 | strncpy(lp->d_typename, ace->sc_params.ModelNumber, 16); | |
2085 | strncpy(lp->d_packname, "fictitious", 16); | 2080 | strncpy(lp->d_packname, "fictitious", 16); | |
2086 | if (ace->sc_capacity > UINT32_MAX) | 2081 | if (ace->sc_capacity > UINT32_MAX) | |
2087 | lp->d_secperunit = UINT32_MAX; | 2082 | lp->d_secperunit = UINT32_MAX; | |
2088 | else | 2083 | else | |
2089 | lp->d_secperunit = ace->sc_capacity; | 2084 | lp->d_secperunit = ace->sc_capacity; | |
2090 | lp->d_rpm = 3600; | 2085 | lp->d_rpm = 3600; | |
2091 | lp->d_interleave = 1; | 2086 | lp->d_interleave = 1; | |
2092 | lp->d_flags = 0; | 2087 | lp->d_flags = 0; | |
2093 | 2088 | |||
2094 | lp->d_partitions[RAW_PART].p_offset = 0; | 2089 | lp->d_partitions[RAW_PART].p_offset = 0; | |
2095 | lp->d_partitions[RAW_PART].p_size = | 2090 | lp->d_partitions[RAW_PART].p_size = | |
2096 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); | 2091 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); | |
2097 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; | 2092 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; | |
2098 | lp->d_npartitions = RAW_PART + 1; | 2093 | lp->d_npartitions = RAW_PART + 1; | |
2099 | 2094 | |||
2100 | lp->d_magic = DISKMAGIC; | 2095 | lp->d_magic = DISKMAGIC; | |
2101 | lp->d_magic2 = DISKMAGIC; | 2096 | lp->d_magic2 = DISKMAGIC; | |
2102 | lp->d_checksum = dkcksum(lp); | 2097 | lp->d_checksum = dkcksum(lp); | |
2103 | } | 2098 | } | |
2104 | 2099 | |||
2105 | /* | 2100 | /* | |
2106 | * Fabricate a default disk label, and try to read the correct one. | 2101 | * Fabricate a default disk label, and try to read the correct one. | |
2107 | */ | 2102 | */ | |
2108 | void | 2103 | void | |
2109 | acegetdisklabel(struct ace_softc *ace) | 2104 | acegetdisklabel(struct ace_softc *ace) | |
2110 | { | 2105 | { | |
2111 | struct disklabel *lp = ace->sc_dk.dk_label; | 2106 | struct disklabel *lp = ace->sc_dk.dk_label; | |
2112 | const char *errstring; | 2107 | const char *errstring; | |
2113 | 2108 | |||
2114 | DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS); | 2109 | DEBUG_PRINT(("acegetdisklabel\n"), DEBUG_FUNCS); | |
2115 | 2110 | |||
2116 | memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); | 2111 | memset(ace->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); | |
2117 | 2112 | |||
2118 | acegetdefaultlabel(ace, lp); | 2113 | acegetdefaultlabel(ace, lp); | |
2119 | 2114 | |||
2120 | #ifdef HAS_BAD144_HANDLING | 2115 | #ifdef HAS_BAD144_HANDLING | |
2121 | ace->sc_bio.badsect[0] = -1; | 2116 | ace->sc_bio.badsect[0] = -1; | |
2122 | #endif | 2117 | #endif | |
2123 | 2118 | |||
2124 | errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev), | 2119 | errstring = readdisklabel(MAKEACEDEV(0, device_unit(ace->sc_dev), | |
2125 | RAW_PART), acestrategy, lp, | 2120 | RAW_PART), acestrategy, lp, | |
2126 | ace->sc_dk.dk_cpulabel); | 2121 | ace->sc_dk.dk_cpulabel); | |
2127 | if (errstring) { | 2122 | if (errstring) { | |
2128 | printf("%s: %s\n", device_xname(ace->sc_dev), errstring); | 2123 | printf("%s: %s\n", device_xname(ace->sc_dev), errstring); | |
2129 | return; | 2124 | return; | |
2130 | } | 2125 | } | |
2131 | 2126 | |||
2132 | #if DEBUG | 2127 | #if DEBUG | |
2133 | if (ACE_DEBUG(DEBUG_WRITES)) { | 2128 | if (ACE_DEBUG(DEBUG_WRITES)) { | |
2134 | int i, n = ace->sc_dk.dk_label->d_npartitions; | 2129 | int i, n = ace->sc_dk.dk_label->d_npartitions; | |
2135 | printf("%s: %d parts\n", device_xname(ace->sc_dev), n); | 2130 | printf("%s: %d parts\n", device_xname(ace->sc_dev), n); | |
2136 | for (i = 0; i < n; i++) { | 2131 | for (i = 0; i < n; i++) { | |
2137 | printf("\t[%d]: t=%x s=%d o=%d\n", i, | 2132 | printf("\t[%d]: t=%x s=%d o=%d\n", i, | |
2138 | ace->sc_dk.dk_label->d_partitions[i].p_fstype, | 2133 | ace->sc_dk.dk_label->d_partitions[i].p_fstype, | |
2139 | ace->sc_dk.dk_label->d_partitions[i].p_size, | 2134 | ace->sc_dk.dk_label->d_partitions[i].p_size, | |
2140 | ace->sc_dk.dk_label->d_partitions[i].p_offset); | 2135 | ace->sc_dk.dk_label->d_partitions[i].p_offset); | |
2141 | } | 2136 | } | |
2142 | } | 2137 | } | |
2143 | #endif | 2138 | #endif | |
2144 | 2139 | |||
2145 | #ifdef HAS_BAD144_HANDLING | 2140 | #ifdef HAS_BAD144_HANDLING | |
2146 | if ((lp->d_flags & D_BADSECT) != 0) | 2141 | if ((lp->d_flags & D_BADSECT) != 0) | |
2147 | bad144intern(ace); | 2142 | bad144intern(ace); | |
2148 | #endif | 2143 | #endif | |
2149 | } | 2144 | } | |
2150 | 2145 | |||
2151 | void | 2146 | void | |
2152 | aceperror(const struct ace_softc *ace) | 2147 | aceperror(const struct ace_softc *ace) | |
2153 | { | 2148 | { | |
2154 | const char *devname = device_xname(ace->sc_dev); | 2149 | const char *devname = device_xname(ace->sc_dev); | |
2155 | uint32_t Status = ace->sc_bio.r_error; | 2150 | uint32_t Status = ace->sc_bio.r_error; | |
2156 | 2151 | |||
2157 | printf("%s: (", devname); | 2152 | printf("%s: (", devname); | |
2158 | 2153 | |||
2159 | if (Status == 0) | 2154 | if (Status == 0) | |
2160 | printf("error not notified"); | 2155 | printf("error not notified"); | |
2161 | else | 2156 | else | |
2162 | printf("status=x%x", Status); | 2157 | printf("status=x%x", Status); | |
2163 | 2158 | |||
2164 | printf(")\n"); | 2159 | printf(")\n"); | |
2165 | } | 2160 | } | |
2166 | 2161 | |||
2167 | int | 2162 | int | |
2168 | aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l) | 2163 | aceioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l) | |
2169 | { | 2164 | { | |
2170 | struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | 2165 | struct ace_softc *ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | |
2171 | int error = 0, s; | 2166 | int error = 0, s; | |
2172 | 2167 | |||
2173 | DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS); | 2168 | DEBUG_PRINT(("aceioctl\n"), DEBUG_FUNCS); | |
2174 | 2169 | |||
2175 | if ((ace->sc_flags & ACEF_LOADED) == 0) | 2170 | if ((ace->sc_flags & ACEF_LOADED) == 0) | |
2176 | return EIO; | 2171 | return EIO; | |
2177 | 2172 | |||
2178 | error = disk_ioctl(&ace->sc_dk, dev, xfer, addr, flag, l); | 2173 | error = disk_ioctl(&ace->sc_dk, dev, xfer, addr, flag, l); | |
2179 | if (error != EPASSTHROUGH) | 2174 | if (error != EPASSTHROUGH) | |
2180 | return error; | 2175 | return error; | |
2181 | 2176 | |||
2182 | switch (xfer) { | 2177 | switch (xfer) { | |
2183 | #ifdef HAS_BAD144_HANDLING | 2178 | #ifdef HAS_BAD144_HANDLING | |
2184 | case DIOCSBAD: | 2179 | case DIOCSBAD: | |
2185 | if ((flag & FWRITE) == 0) | 2180 | if ((flag & FWRITE) == 0) | |
2186 | return EBADF; | 2181 | return EBADF; | |
2187 | ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; | 2182 | ace->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; | |
2188 | ace->sc_dk.dk_label->d_flags |= D_BADSECT; | 2183 | ace->sc_dk.dk_label->d_flags |= D_BADSECT; | |
2189 | bad144intern(ace); | 2184 | bad144intern(ace); | |
2190 | return 0; | 2185 | return 0; | |
2191 | #endif | 2186 | #endif | |
2192 | 2187 | |||
2193 | case DIOCWDINFO: | 2188 | case DIOCWDINFO: | |
2194 | case DIOCSDINFO: | 2189 | case DIOCSDINFO: | |
2195 | { | 2190 | { | |
2196 | struct disklabel *lp; | 2191 | struct disklabel *lp; | |
2197 | 2192 | |||
2198 | if ((flag & FWRITE) == 0) | 2193 | if ((flag & FWRITE) == 0) | |
2199 | return EBADF; | 2194 | return EBADF; | |
2200 | 2195 | |||
2201 | lp = (struct disklabel *)addr; | 2196 | lp = (struct disklabel *)addr; | |
2202 | 2197 | |||
2203 | mutex_enter(&ace->sc_dk.dk_openlock); | 2198 | mutex_enter(&ace->sc_dk.dk_openlock); | |
2204 | ace->sc_flags |= ACEF_LABELLING; | 2199 | ace->sc_flags |= ACEF_LABELLING; | |
2205 | 2200 | |||
2206 | error = setdisklabel(ace->sc_dk.dk_label, | 2201 | error = setdisklabel(ace->sc_dk.dk_label, | |
2207 | lp, /*ace->sc_dk.dk_openmask : */0, | 2202 | lp, /*ace->sc_dk.dk_openmask : */0, | |
2208 | ace->sc_dk.dk_cpulabel); | 2203 | ace->sc_dk.dk_cpulabel); | |
2209 | if (error == 0) { | 2204 | if (error == 0) { | |
2210 | if (xfer == DIOCWDINFO) | 2205 | if (xfer == DIOCWDINFO) | |
2211 | error = writedisklabel(ACELABELDEV(dev), | 2206 | error = writedisklabel(ACELABELDEV(dev), | |
2212 | acestrategy, ace->sc_dk.dk_label, | 2207 | acestrategy, ace->sc_dk.dk_label, | |
2213 | ace->sc_dk.dk_cpulabel); | 2208 | ace->sc_dk.dk_cpulabel); | |
2214 | } | 2209 | } | |
2215 | 2210 | |||
2216 | ace->sc_flags &= ~ACEF_LABELLING; | 2211 | ace->sc_flags &= ~ACEF_LABELLING; | |
2217 | mutex_exit(&ace->sc_dk.dk_openlock); | 2212 | mutex_exit(&ace->sc_dk.dk_openlock); | |
2218 | return error; | 2213 | return error; | |
2219 | } | 2214 | } | |
2220 | 2215 | |||
2221 | case DIOCKLABEL: | 2216 | case DIOCKLABEL: | |
2222 | if (*(int *)addr) | 2217 | if (*(int *)addr) | |
2223 | ace->sc_flags |= ACEF_KLABEL; | 2218 | ace->sc_flags |= ACEF_KLABEL; | |
2224 | else | 2219 | else | |
2225 | ace->sc_flags &= ~ACEF_KLABEL; | 2220 | ace->sc_flags &= ~ACEF_KLABEL; | |
2226 | return 0; | 2221 | return 0; | |
2227 | 2222 | |||
2228 | case DIOCWLABEL: | 2223 | case DIOCWLABEL: | |
2229 | if ((flag & FWRITE) == 0) | 2224 | if ((flag & FWRITE) == 0) | |
2230 | return EBADF; | 2225 | return EBADF; | |
2231 | if (*(int *)addr) | 2226 | if (*(int *)addr) | |
2232 | ace->sc_flags |= ACEF_WLABEL; | 2227 | ace->sc_flags |= ACEF_WLABEL; | |
2233 | else | 2228 | else | |
2234 | ace->sc_flags &= ~ACEF_WLABEL; | 2229 | ace->sc_flags &= ~ACEF_WLABEL; | |
2235 | return 0; | 2230 | return 0; | |
2236 | 2231 | |||
2237 | case DIOCGDEFLABEL: | 2232 | case DIOCGDEFLABEL: | |
2238 | acegetdefaultlabel(ace, (struct disklabel *)addr); | 2233 | acegetdefaultlabel(ace, (struct disklabel *)addr); | |
2239 | return 0; | 2234 | return 0; | |
2240 | 2235 | |||
2241 | case DIOCCACHESYNC: | 2236 | case DIOCCACHESYNC: | |
2242 | return 0; | 2237 | return 0; | |
2243 | 2238 | |||
2244 | case DIOCGSTRATEGY: | 2239 | case DIOCGSTRATEGY: | |
2245 | { | 2240 | { | |
2246 | struct disk_strategy *dks = (void *)addr; | 2241 | struct disk_strategy *dks = (void *)addr; | |
2247 | 2242 | |||
2248 | s = splbio(); | 2243 | s = splbio(); | |
2249 | strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q), | 2244 | strlcpy(dks->dks_name, bufq_getstrategyname(ace->sc_q), | |
2250 | sizeof(dks->dks_name)); | 2245 | sizeof(dks->dks_name)); | |
2251 | splx(s); | 2246 | splx(s); | |
2252 | dks->dks_paramlen = 0; | 2247 | dks->dks_paramlen = 0; | |
2253 | 2248 | |||
2254 | return 0; | 2249 | return 0; | |
2255 | } | 2250 | } | |
2256 | 2251 | |||
2257 | case DIOCSSTRATEGY: | 2252 | case DIOCSSTRATEGY: | |
2258 | { | 2253 | { | |
2259 | struct disk_strategy *dks = (void *)addr; | 2254 | struct disk_strategy *dks = (void *)addr; | |
2260 | struct bufq_state *new; | 2255 | struct bufq_state *new; | |
2261 | struct bufq_state *old; | 2256 | struct bufq_state *old; | |
2262 | 2257 | |||
2263 | if ((flag & FWRITE) == 0) { | 2258 | if ((flag & FWRITE) == 0) { | |
2264 | return EBADF; | 2259 | return EBADF; | |
2265 | } | 2260 | } | |
2266 | if (dks->dks_param != NULL) { | 2261 | if (dks->dks_param != NULL) { | |
2267 | return EINVAL; | 2262 | return EINVAL; | |
2268 | } | 2263 | } | |
2269 | dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ | 2264 | dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ | |
2270 | error = bufq_alloc(&new, dks->dks_name, | 2265 | error = bufq_alloc(&new, dks->dks_name, | |
2271 | BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); | 2266 | BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); | |
2272 | if (error) { | 2267 | if (error) { | |
2273 | return error; | 2268 | return error; | |
2274 | } | 2269 | } | |
2275 | s = splbio(); | 2270 | s = splbio(); | |
2276 | old = ace->sc_q; | 2271 | old = ace->sc_q; | |
2277 | bufq_move(new, old); | 2272 | bufq_move(new, old); | |
2278 | ace->sc_q = new; | 2273 | ace->sc_q = new; | |
2279 | splx(s); | 2274 | splx(s); | |
2280 | bufq_free(old); | 2275 | bufq_free(old); | |
2281 | 2276 | |||
2282 | return 0; | 2277 | return 0; | |
2283 | } | 2278 | } | |
2284 | 2279 | |||
2285 | #ifdef USE_ACE_FOR_RECONFIG | 2280 | #ifdef USE_ACE_FOR_RECONFIG | |
2286 | /* | 2281 | /* | |
2287 | * Ok, how do I get this standardized | 2282 | * Ok, how do I get this standardized | |
2288 | * [nothing to do with disks either] | 2283 | * [nothing to do with disks either] | |
2289 | */ | 2284 | */ | |
2290 | #define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt) | 2285 | #define DIOC_FPGA_RECONFIGURE _IOW('d',166, struct ioctl_pt) | |
2291 | case DIOC_FPGA_RECONFIGURE: | 2286 | case DIOC_FPGA_RECONFIGURE: | |
2292 | { | 2287 | { | |
2293 | /* | 2288 | /* | |
2294 | * BUGBUG This is totally wrong, we need to fault in | 2289 | * BUGBUG This is totally wrong, we need to fault in | |
2295 | * all data in advance. | 2290 | * all data in advance. | |
2296 | * Otherwise we get back here with the sysace in a bad state | 2291 | * Otherwise we get back here with the sysace in a bad state | |
2297 | * (its NOT reentrant!) | 2292 | * (its NOT reentrant!) | |
2298 | */ | 2293 | */ | |
2299 | struct ioctl_pt *pt = (struct ioctl_pt *)addr; | 2294 | struct ioctl_pt *pt = (struct ioctl_pt *)addr; | |
2300 | return sysace_send_config(ace,(uint32_t*)pt->data,pt->com); | 2295 | return sysace_send_config(ace,(uint32_t*)pt->data,pt->com); | |
2301 | } | 2296 | } | |
2302 | #endif /* USE_ACE_FOR_RECONFIG */ | 2297 | #endif /* USE_ACE_FOR_RECONFIG */ | |
2303 | 2298 | |||
2304 | default: | 2299 | default: | |
2305 | /* | 2300 | /* | |
2306 | * NB: we get a DIOCGWEDGEINFO, but nobody else handles it | 2301 | * NB: we get a DIOCGWEDGEINFO, but nobody else handles it | |
2307 | * either | 2302 | * either | |
2308 | */ | 2303 | */ | |
2309 | DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS); | 2304 | DEBUG_PRINT(("aceioctl: unsup x%lx\n", xfer), DEBUG_FUNCS); | |
2310 | return ENOTTY; | 2305 | return ENOTTY; | |
2311 | } | 2306 | } | |
2312 | } | 2307 | } | |
2313 | 2308 | |||
2314 | int | 2309 | int | |
2315 | acesize(dev_t dev) | 2310 | acesize(dev_t dev) | |
2316 | { | 2311 | { | |
2317 | struct ace_softc *ace; | 2312 | struct ace_softc *ace; | |
2318 | int part, omask; | 2313 | int part, omask; | |
2319 | int size; | 2314 | int size; | |
2320 | 2315 | |||
2321 | DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS); | 2316 | DEBUG_PRINT(("acesize\n"), DEBUG_FUNCS); | |
2322 | 2317 | |||
2323 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | 2318 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | |
2324 | if (ace == NULL) | 2319 | if (ace == NULL) | |
2325 | return -1; | 2320 | return -1; | |
2326 | 2321 | |||
2327 | part = ACEPART(dev); | 2322 | part = ACEPART(dev); | |
2328 | omask = ace->sc_dk.dk_openmask & (1 << part); | 2323 | omask = ace->sc_dk.dk_openmask & (1 << part); | |
2329 | 2324 | |||
2330 | if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0) | 2325 | if (omask == 0 && aceopen(dev, 0, S_IFBLK, NULL) != 0) | |
2331 | return -1; | 2326 | return -1; | |
2332 | if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) | 2327 | if (ace->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) | |
2333 | size = -1; | 2328 | size = -1; | |
2334 | else | 2329 | else | |
2335 | size = ace->sc_dk.dk_label->d_partitions[part].p_size * | 2330 | size = ace->sc_dk.dk_label->d_partitions[part].p_size * | |
2336 | (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE); | 2331 | (ace->sc_dk.dk_label->d_secsize / DEV_BSIZE); | |
2337 | if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0) | 2332 | if (omask == 0 && aceclose(dev, 0, S_IFBLK, NULL) != 0) | |
2338 | return -1; | 2333 | return -1; | |
2339 | return size; | 2334 | return size; | |
2340 | } | 2335 | } | |
2341 | 2336 | |||
2342 | /* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */ | 2337 | /* #define ACE_DUMP_NOT_TRUSTED if you just want to watch */ | |
2343 | #define ACE_DUMP_NOT_TRUSTED | 2338 | #define ACE_DUMP_NOT_TRUSTED | |
2344 | static int acedoingadump = 0; | 2339 | static int acedoingadump = 0; | |
2345 | 2340 | |||
2346 | /* | 2341 | /* | |
2347 | * Dump core after a system crash. | 2342 | * Dump core after a system crash. | |
2348 | */ | 2343 | */ | |
2349 | int | 2344 | int | |
2350 | acedump(dev_t dev, daddr_t blkno, void *va, size_t size) | 2345 | acedump(dev_t dev, daddr_t blkno, void *va, size_t size) | |
2351 | { | 2346 | { | |
2352 | struct ace_softc *ace; /* disk unit to do the I/O */ | 2347 | struct ace_softc *ace; /* disk unit to do the I/O */ | |
2353 | struct disklabel *lp; /* disk's disklabel */ | 2348 | struct disklabel *lp; /* disk's disklabel */ | |
2354 | int part, err; | 2349 | int part, err; | |
2355 | int nblks; /* total number of sectors left to write */ | 2350 | int nblks; /* total number of sectors left to write */ | |
2356 | 2351 | |||
2357 | /* Check if recursive dump; if so, punt. */ | 2352 | /* Check if recursive dump; if so, punt. */ | |
2358 | if (acedoingadump) | 2353 | if (acedoingadump) | |
2359 | return EFAULT; | 2354 | return EFAULT; | |
2360 | acedoingadump = 1; | 2355 | acedoingadump = 1; | |
2361 | 2356 | |||
2362 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | 2357 | ace = device_lookup_private(&ace_cd, ACEUNIT(dev)); | |
2363 | if (ace == NULL) | 2358 | if (ace == NULL) | |
2364 | return ENXIO; | 2359 | return ENXIO; | |
2365 | 2360 | |||
2366 | part = ACEPART(dev); | 2361 | part = ACEPART(dev); | |
2367 | 2362 | |||
2368 | /* Convert to disk sectors. Request must be a multiple of size. */ | 2363 | /* Convert to disk sectors. Request must be a multiple of size. */ | |
2369 | lp = ace->sc_dk.dk_label; | 2364 | lp = ace->sc_dk.dk_label; | |
2370 | if ((size % lp->d_secsize) != 0) | 2365 | if ((size % lp->d_secsize) != 0) | |
2371 | return EFAULT; | 2366 | return EFAULT; | |
2372 | nblks = size / lp->d_secsize; | 2367 | nblks = size / lp->d_secsize; | |
2373 | blkno = blkno / (lp->d_secsize / DEV_BSIZE); | 2368 | blkno = blkno / (lp->d_secsize / DEV_BSIZE); | |
2374 | 2369 | |||
2375 | /* Check transfer bounds against partition size. */ | 2370 | /* Check transfer bounds against partition size. */ | |
2376 | if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size)) | 2371 | if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size)) | |
2377 | return EINVAL; | 2372 | return EINVAL; | |
2378 | 2373 | |||
2379 | /* Offset block number to start of partition. */ | 2374 | /* Offset block number to start of partition. */ | |
2380 | blkno += lp->d_partitions[part].p_offset; | 2375 | blkno += lp->d_partitions[part].p_offset; | |
2381 | 2376 | |||
2382 | ace->sc_bp = NULL; | 2377 | ace->sc_bp = NULL; | |
2383 | ace->sc_bio.blkno = blkno; | 2378 | ace->sc_bio.blkno = blkno; | |
2384 | ace->sc_bio.flags = ATA_POLL; | 2379 | ace->sc_bio.flags = ATA_POLL; | |
2385 | ace->sc_bio.nbytes = nblks * lp->d_secsize; | 2380 | ace->sc_bio.nbytes = nblks * lp->d_secsize; | |
2386 | ace->sc_bio.databuf = va; | 2381 | ace->sc_bio.databuf = va; | |
2387 | #ifndef ACE_DUMP_NOT_TRUSTED | 2382 | #ifndef ACE_DUMP_NOT_TRUSTED | |
2388 | ace->active_xfer = bp; | 2383 | ace->active_xfer = bp; | |
2389 | wakeup(&ace->ch_thread); | 2384 | wakeup(&ace->ch_thread); | |
2390 | 2385 | |||
2391 | switch(ace->sc_bio.error) { | 2386 | switch(ace->sc_bio.error) { | |
2392 | case ETIMEDOUT: | 2387 | case ETIMEDOUT: | |
2393 | printf("acedump: device timed out"); | 2388 | printf("acedump: device timed out"); | |
2394 | err = EIO; | 2389 | err = EIO; | |
2395 | break; | 2390 | break; | |
2396 | case 0: | 2391 | case 0: | |
2397 | err = 0; | 2392 | err = 0; | |
2398 | break; | 2393 | break; | |
2399 | default: | 2394 | default: | |
2400 | panic("acedump: unknown error type"); | 2395 | panic("acedump: unknown error type"); | |
2401 | } | 2396 | } | |
2402 | if (err != 0) { | 2397 | if (err != 0) { | |
2403 | printf("\n"); | 2398 | printf("\n"); | |
2404 | return err; | 2399 | return err; | |
2405 | } | 2400 | } | |
2406 | #else /* ACE_DUMP_NOT_TRUSTED */ | 2401 | #else /* ACE_DUMP_NOT_TRUSTED */ | |
2407 | /* Let's just talk about this first... */ | 2402 | /* Let's just talk about this first... */ | |
2408 | device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n", | 2403 | device_printf(ace->sc_dev, ": dump addr 0x%p, size %zu blkno %llx\n", | |
2409 | va, size, blkno); | 2404 | va, size, blkno); | |
2410 | DELAY(500 * 1000); /* half a second */ | 2405 | DELAY(500 * 1000); /* half a second */ | |
2411 | err = 0; | 2406 | err = 0; | |
2412 | __USE(err); | 2407 | __USE(err); | |
2413 | #endif | 2408 | #endif | |
2414 | 2409 | |||
2415 | acedoingadump = 0; | 2410 | acedoingadump = 0; | |
2416 | return 0; | 2411 | return 0; | |
2417 | } | 2412 | } | |
2418 | 2413 | |||
2419 | #ifdef HAS_BAD144_HANDLING | 2414 | #ifdef HAS_BAD144_HANDLING | |
2420 | /* | 2415 | /* | |
2421 | * Internalize the bad sector table. | 2416 | * Internalize the bad sector table. | |
2422 | */ | 2417 | */ | |
2423 | void | 2418 | void | |
2424 | bad144intern(struct ace_softc *ace) | 2419 | bad144intern(struct ace_softc *ace) | |
2425 | { | 2420 | { | |
2426 | struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad; | 2421 | struct dkbad *bt = &ace->sc_dk.dk_cpulabel->bad; | |
2427 | struct disklabel *lp = ace->sc_dk.dk_label; | 2422 | struct disklabel *lp = ace->sc_dk.dk_label; | |
2428 | int i = 0; | 2423 | int i = 0; | |
2429 | 2424 | |||
2430 | DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); | 2425 | DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); | |
2431 | 2426 | |||
2432 | for (; i < NBT_BAD; i++) { | 2427 | for (; i < NBT_BAD; i++) { | |
2433 | if (bt->bt_bad[i].bt_cyl == 0xffff) | 2428 | if (bt->bt_bad[i].bt_cyl == 0xffff) | |
2434 | break; | 2429 | break; | |
2435 | ace->sc_bio.badsect[i] = | 2430 | ace->sc_bio.badsect[i] = | |
2436 | bt->bt_bad[i].bt_cyl * lp->d_secpercyl + | 2431 | bt->bt_bad[i].bt_cyl * lp->d_secpercyl + | |
2437 | (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + | 2432 | (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + | |
2438 | (bt->bt_bad[i].bt_trksec & 0xff); | 2433 | (bt->bt_bad[i].bt_trksec & 0xff); | |
2439 | } | 2434 | } | |
2440 | for (; i < NBT_BAD+1; i++) | 2435 | for (; i < NBT_BAD+1; i++) | |
2441 | ace->sc_bio.badsect[i] = -1; | 2436 | ace->sc_bio.badsect[i] = -1; | |
2442 | } | 2437 | } | |
2443 | #endif | 2438 | #endif | |
2444 | 2439 | |||
2445 | static void | 2440 | static void | |
2446 | ace_set_geometry(struct ace_softc *ace) | 2441 | ace_set_geometry(struct ace_softc *ace) | |
2447 | { | 2442 | { | |
2448 | struct disk_geom *dg = &ace->sc_dk.dk_geom; | 2443 | struct disk_geom *dg = &ace->sc_dk.dk_geom; | |
2449 | 2444 | |||
2450 | memset(dg, 0, sizeof(*dg)); | 2445 | memset(dg, 0, sizeof(*dg)); | |
2451 | 2446 | |||
2452 | dg->dg_secperunit = ace->sc_capacity; | 2447 | dg->dg_secperunit = ace->sc_capacity; | |
2453 | dg->dg_secsize = DEV_BSIZE /* XXX 512? */; | 2448 | dg->dg_secsize = DEV_BSIZE /* XXX 512? */; | |
2454 | dg->dg_nsectors = ace->sc_params.CurrentSectorsPerTrack; | 2449 | dg->dg_nsectors = ace->sc_params.CurrentSectorsPerTrack; | |
2455 | dg->dg_ntracks = ace->sc_params.CurrentNumberOfHeads; | 2450 | dg->dg_ntracks = ace->sc_params.CurrentNumberOfHeads; | |
2456 | 2451 | |||
2457 | disk_set_info(ace->sc_dev, &ace->sc_dk, ST506); | 2452 | disk_set_info(ace->sc_dev, &ace->sc_dk, ST506); | |
2458 | } | 2453 | } |
--- src/sys/arch/emips/ebus/flash_ebus.c 2018/03/04 21:41:48 1.20
+++ src/sys/arch/emips/ebus/flash_ebus.c 2019/12/08 14:43:16 1.20.8.1
@@ -1,2287 +1,2282 @@ | @@ -1,2287 +1,2282 @@ | |||
1 | /* $NetBSD: flash_ebus.c,v 1.20 2018/03/04 21:41:48 mrg Exp $ */ | 1 | /* $NetBSD: flash_ebus.c,v 1.20.8.1 2019/12/08 14:43:16 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code was written by Alessandro Forin and Neil Pittman | 7 | * This code was written by Alessandro Forin and Neil Pittman | |
8 | * at Microsoft Research and contributed to The NetBSD Foundation | 8 | * at Microsoft Research and contributed to The NetBSD Foundation | |
9 | * by Microsoft Corporation. | 9 | * by Microsoft Corporation. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | 33 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | |
34 | __KERNEL_RCSID(0, "$NetBSD: flash_ebus.c,v 1.20 2018/03/04 21:41:48 mrg Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: flash_ebus.c,v 1.20.8.1 2019/12/08 14:43:16 martin Exp $"); | |
35 | 35 | |||
36 | /* Driver for the Intel 28F320/640/128 (J3A150) StrataFlash memory device | 36 | /* Driver for the Intel 28F320/640/128 (J3A150) StrataFlash memory device | |
37 | * Extended to include the Intel JS28F256P30T95. | 37 | * Extended to include the Intel JS28F256P30T95. | |
38 | */ | 38 | */ | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/systm.h> | 41 | #include <sys/systm.h> | |
42 | #include <sys/kernel.h> | 42 | #include <sys/kernel.h> | |
43 | #include <sys/proc.h> | 43 | #include <sys/proc.h> | |
44 | #include <sys/errno.h> | 44 | #include <sys/errno.h> | |
45 | #include <sys/ioctl.h> | 45 | #include <sys/ioctl.h> | |
46 | #include <sys/device.h> | 46 | #include <sys/device.h> | |
47 | #include <sys/conf.h> | 47 | #include <sys/conf.h> | |
48 | #include <sys/file.h> | 48 | #include <sys/file.h> | |
49 | #include <sys/stat.h> | 49 | #include <sys/stat.h> | |
50 | #include <sys/ioctl.h> | 50 | #include <sys/ioctl.h> | |
51 | #include <sys/buf.h> | 51 | #include <sys/buf.h> | |
52 | #include <sys/bufq.h> | 52 | #include <sys/bufq.h> | |
53 | #include <sys/uio.h> | 53 | #include <sys/uio.h> | |
54 | #include <sys/malloc.h> | 54 | #include <sys/malloc.h> | |
55 | #include <uvm/uvm_extern.h> | 55 | #include <uvm/uvm_extern.h> | |
56 | #include <sys/disklabel.h> | 56 | #include <sys/disklabel.h> | |
57 | #include <sys/disk.h> | 57 | #include <sys/disk.h> | |
58 | #include <sys/syslog.h> | 58 | #include <sys/syslog.h> | |
59 | #include <sys/vnode.h> | 59 | #include <sys/vnode.h> | |
60 | #include <sys/kthread.h> | 60 | #include <sys/kthread.h> | |
61 | #include <sys/lock.h> | 61 | #include <sys/lock.h> | |
62 | #include <sys/queue.h> | 62 | #include <sys/queue.h> | |
63 | 63 | |||
64 | #include <sys/rndsource.h> | 64 | #include <sys/rndsource.h> | |
65 | 65 | |||
66 | #include "locators.h" | 66 | #include "locators.h" | |
67 | #include <prop/proplib.h> | 67 | #include <prop/proplib.h> | |
68 | 68 | |||
69 | #include <emips/ebus/ebusvar.h> | 69 | #include <emips/ebus/ebusvar.h> | |
70 | #include <emips/emips/machdep.h> | 70 | #include <emips/emips/machdep.h> | |
71 | #include <machine/emipsreg.h> | 71 | #include <machine/emipsreg.h> | |
72 | 72 | |||
73 | /* Internal config switches | 73 | /* Internal config switches | |
74 | */ | 74 | */ | |
75 | #define USE_BUFFERED_WRITES 0 /* Faster, but might not work in some (older) cases */ | 75 | #define USE_BUFFERED_WRITES 0 /* Faster, but might not work in some (older) cases */ | |
76 | #define Verbose 0 | 76 | #define Verbose 0 | |
77 | 77 | |||
78 | /* Debug tools | 78 | /* Debug tools | |
79 | */ | 79 | */ | |
80 | #define DEBUG_INTR 0x01 | 80 | #define DEBUG_INTR 0x01 | |
81 | #define DEBUG_XFERS 0x02 | 81 | #define DEBUG_XFERS 0x02 | |
82 | #define DEBUG_STATUS 0x04 | 82 | #define DEBUG_STATUS 0x04 | |
83 | #define DEBUG_FUNCS 0x08 | 83 | #define DEBUG_FUNCS 0x08 | |
84 | #define DEBUG_PROBE 0x10 | 84 | #define DEBUG_PROBE 0x10 | |
85 | #define DEBUG_WRITES 0x20 | 85 | #define DEBUG_WRITES 0x20 | |
86 | #define DEBUG_READS 0x40 | 86 | #define DEBUG_READS 0x40 | |
87 | #define DEBUG_ERRORS 0x80 | 87 | #define DEBUG_ERRORS 0x80 | |
88 | #ifdef DEBUG | 88 | #ifdef DEBUG | |
89 | int eflash_debug = DEBUG_ERRORS; | 89 | int eflash_debug = DEBUG_ERRORS; | |
90 | #define EFLASH_DEBUG(x) (eflash_debug & (x)) | 90 | #define EFLASH_DEBUG(x) (eflash_debug & (x)) | |
91 | #define DBGME(_lev_,_x_) if ((_lev_) & eflash_debug) _x_ | 91 | #define DBGME(_lev_,_x_) if ((_lev_) & eflash_debug) _x_ | |
92 | #else | 92 | #else | |
93 | #define EFLASH_DEBUG(x) (0) | 93 | #define EFLASH_DEBUG(x) (0) | |
94 | #define DBGME(_lev_,_x_) | 94 | #define DBGME(_lev_,_x_) | |
95 | #endif | 95 | #endif | |
96 | #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_) | 96 | #define DEBUG_PRINT(_args_,_lev_) DBGME(_lev_,printf _args_) | |
97 | 97 | |||
98 | /* Product ID codes | 98 | /* Product ID codes | |
99 | */ | 99 | */ | |
100 | #define MANUF_INTEL 0x89 | 100 | #define MANUF_INTEL 0x89 | |
101 | #define DEVICE_320 0x16 | 101 | #define DEVICE_320 0x16 | |
102 | #define DEVICE_640 0x17 | 102 | #define DEVICE_640 0x17 | |
103 | #define DEVICE_128 0x18 | 103 | #define DEVICE_128 0x18 | |
104 | #define DEVICE_256 0x19 | 104 | #define DEVICE_256 0x19 | |
105 | 105 | |||
106 | /* Table of chips we understand. | 106 | /* Table of chips we understand. | |
107 | */ | 107 | */ | |
108 | #define nDELTAS 3 | 108 | #define nDELTAS 3 | |
109 | struct flash_type { | 109 | struct flash_type { | |
110 | struct { | 110 | struct { | |
111 | uint32_t nSectors; | 111 | uint32_t nSectors; | |
112 | uint32_t nKB; | 112 | uint32_t nKB; | |
113 | } ft_deltas[nDELTAS]; | 113 | } ft_deltas[nDELTAS]; | |
114 | uint8_t ft_manuf_code; | 114 | uint8_t ft_manuf_code; | |
115 | uint8_t ft_device_code; | 115 | uint8_t ft_device_code; | |
116 | uint16_t ft_total_sectors; | 116 | uint16_t ft_total_sectors; | |
117 | const char *ft_name; | 117 | const char *ft_name; | |
118 | }; | 118 | }; | |
119 | 119 | |||
120 | static const struct flash_type sector_maps[] = { | 120 | static const struct flash_type sector_maps[] = { | |
121 | { | 121 | { | |
122 | {{32,128},{0,0},}, | 122 | {{32,128},{0,0},}, | |
123 | MANUF_INTEL, DEVICE_320, 32, /* a J3 part */ | 123 | MANUF_INTEL, DEVICE_320, 32, /* a J3 part */ | |
124 | "StrataFlash 28F320" | 124 | "StrataFlash 28F320" | |
125 | }, | 125 | }, | |
126 | { | 126 | { | |
127 | {{64,128},{0,0},}, | 127 | {{64,128},{0,0},}, | |
128 | MANUF_INTEL, DEVICE_640, 64, /* a J3 part */ | 128 | MANUF_INTEL, DEVICE_640, 64, /* a J3 part */ | |
129 | "StrataFlash 28F640" | 129 | "StrataFlash 28F640" | |
130 | }, | 130 | }, | |
131 | { | 131 | { | |
132 | {{128,128},{0,0},}, | 132 | {{128,128},{0,0},}, | |
133 | MANUF_INTEL, DEVICE_128, 128, /* a J3 part */ | 133 | MANUF_INTEL, DEVICE_128, 128, /* a J3 part */ | |
134 | "StrataFlash 28F128" | 134 | "StrataFlash 28F128" | |
135 | }, | 135 | }, | |
136 | { | 136 | { | |
137 | {{255,128},{4,32},{0,0}}, | 137 | {{255,128},{4,32},{0,0}}, | |
138 | MANUF_INTEL, DEVICE_256, 259, /* a P30 part */ | 138 | MANUF_INTEL, DEVICE_256, 259, /* a P30 part */ | |
139 | "StrataFlash 28F256" | 139 | "StrataFlash 28F256" | |
140 | } | 140 | } | |
141 | }; | 141 | }; | |
142 | #define nMAPS ((sizeof sector_maps) / (sizeof sector_maps[0])) | 142 | #define nMAPS ((sizeof sector_maps) / (sizeof sector_maps[0])) | |
143 | 143 | |||
144 | /* Instead of dragging in atavar.h.. */ | 144 | /* Instead of dragging in atavar.h.. */ | |
145 | struct eflash_bio { | 145 | struct eflash_bio { | |
146 | volatile int flags;/* cmd flags */ | 146 | volatile int flags;/* cmd flags */ | |
147 | #define ATA_POLL 0x0002 /* poll for completion */ | 147 | #define ATA_POLL 0x0002 /* poll for completion */ | |
148 | #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */ | 148 | #define ATA_SINGLE 0x0008 /* transfer must be done in singlesector mode */ | |
149 | #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */ | 149 | #define ATA_READ 0x0020 /* transfer is a read (otherwise a write) */ | |
150 | #define ATA_CORR 0x0040 /* transfer had a corrected error */ | 150 | #define ATA_CORR 0x0040 /* transfer had a corrected error */ | |
151 | daddr_t blkno; /* block addr */ | 151 | daddr_t blkno; /* block addr */ | |
152 | daddr_t blkdone;/* number of blks transferred */ | 152 | daddr_t blkdone;/* number of blks transferred */ | |
153 | size_t nblks; /* number of blocks currently transferring */ | 153 | size_t nblks; /* number of blocks currently transferring */ | |
154 | size_t nbytes; /* number of bytes currently transferring */ | 154 | size_t nbytes; /* number of bytes currently transferring */ | |
155 | char *databuf;/* data buffer address */ | 155 | char *databuf;/* data buffer address */ | |
156 | volatile int error; | 156 | volatile int error; | |
157 | u_int32_t r_error;/* copy of status register */ | 157 | u_int32_t r_error;/* copy of status register */ | |
158 | #ifdef HAS_BAD144_HANDLING | 158 | #ifdef HAS_BAD144_HANDLING | |
159 | daddr_t badsect[127];/* 126 plus trailing -1 marker */ | 159 | daddr_t badsect[127];/* 126 plus trailing -1 marker */ | |
160 | #endif | 160 | #endif | |
161 | }; | 161 | }; | |
162 | /* End of atavar.h*/ | 162 | /* End of atavar.h*/ | |
163 | 163 | |||
164 | /* chip-specific functions | 164 | /* chip-specific functions | |
165 | */ | 165 | */ | |
166 | struct flash_ops; | 166 | struct flash_ops; | |
167 | 167 | |||
168 | /* | 168 | /* | |
169 | * Device softc | 169 | * Device softc | |
170 | */ | 170 | */ | |
171 | struct eflash_softc { | 171 | struct eflash_softc { | |
172 | device_t sc_dev; | 172 | device_t sc_dev; | |
173 | 173 | |||
174 | /* General disk infos */ | 174 | /* General disk infos */ | |
175 | struct disk sc_dk; | 175 | struct disk sc_dk; | |
176 | struct bufq_state *sc_q; | 176 | struct bufq_state *sc_q; | |
177 | struct callout sc_restart_ch; | 177 | struct callout sc_restart_ch; | |
178 | 178 | |||
179 | /* IDE disk soft states */ | 179 | /* IDE disk soft states */ | |
180 | struct buf *sc_bp; /* buf being transfered */ | 180 | struct buf *sc_bp; /* buf being transfered */ | |
181 | struct buf *active_xfer; /* buf handoff to thread */ | 181 | struct buf *active_xfer; /* buf handoff to thread */ | |
182 | struct eflash_bio sc_bio; /* current transfer */ | 182 | struct eflash_bio sc_bio; /* current transfer */ | |
183 | 183 | |||
184 | struct proc *ch_thread; | 184 | struct proc *ch_thread; | |
185 | int ch_flags; | 185 | int ch_flags; | |
186 | #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */ | 186 | #define ATACH_SHUTDOWN 0x02 /* thread is shutting down */ | |
187 | #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */ | 187 | #define ATACH_IRQ_WAIT 0x10 /* thread is waiting for irq */ | |
188 | #define ATACH_DISABLED 0x80 /* channel is disabled */ | 188 | #define ATACH_DISABLED 0x80 /* channel is disabled */ | |
189 | #define ATACH_TH_RUN 0x100 /* the kernel thread is working */ | 189 | #define ATACH_TH_RUN 0x100 /* the kernel thread is working */ | |
190 | #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ | 190 | #define ATACH_TH_RESET 0x200 /* someone ask the thread to reset */ | |
191 | 191 | |||
192 | int openings; | 192 | int openings; | |
193 | int sc_flags; | 193 | int sc_flags; | |
194 | #define EFLASHF_WLABEL 0x004 /* label is writable */ | 194 | #define EFLASHF_WLABEL 0x004 /* label is writable */ | |
195 | #define EFLASHF_LABELLING 0x008 /* writing label */ | 195 | #define EFLASHF_LABELLING 0x008 /* writing label */ | |
196 | #define EFLASHF_LOADED 0x010 /* parameters loaded */ | 196 | #define EFLASHF_LOADED 0x010 /* parameters loaded */ | |
197 | #define EFLASHF_WAIT 0x020 /* waiting for resources */ | 197 | #define EFLASHF_WAIT 0x020 /* waiting for resources */ | |
198 | #define EFLASHF_KLABEL 0x080 /* retain label after 'full' close */ | 198 | #define EFLASHF_KLABEL 0x080 /* retain label after 'full' close */ | |
199 | 199 | |||
200 | int retries; /* number of xfer retry */ | 200 | int retries; /* number of xfer retry */ | |
201 | 201 | |||
202 | krndsource_t rnd_source; | 202 | krndsource_t rnd_source; | |
203 | 203 | |||
204 | /* flash-specific state */ | 204 | /* flash-specific state */ | |
205 | struct _Flash *sc_dp; | 205 | struct _Flash *sc_dp; | |
206 | uint32_t sc_size; | 206 | uint32_t sc_size; | |
207 | uint32_t sc_capacity; | 207 | uint32_t sc_capacity; | |
208 | paddr_t sc_base; | 208 | paddr_t sc_base; | |
209 | volatile uint8_t *sc_page0; | 209 | volatile uint8_t *sc_page0; | |
210 | 210 | |||
211 | /* current read-write sector mapping */ | 211 | /* current read-write sector mapping */ | |
212 | /*volatile*/ uint8_t *sc_sector; | 212 | /*volatile*/ uint8_t *sc_sector; | |
213 | uint32_t sc_sector_size; | 213 | uint32_t sc_sector_size; | |
214 | uint32_t sc_sector_offset; | 214 | uint32_t sc_sector_offset; | |
215 | #define NOSECTOR ((uint32_t)(~0)) | 215 | #define NOSECTOR ((uint32_t)(~0)) | |
216 | int sc_erased; | 216 | int sc_erased; | |
217 | 217 | |||
218 | /* device-specificity */ | 218 | /* device-specificity */ | |
219 | uint32_t sc_buffersize; | 219 | uint32_t sc_buffersize; | |
220 | vsize_t sc_max_secsize; | 220 | vsize_t sc_max_secsize; | |
221 | unsigned int sc_chips; | 221 | unsigned int sc_chips; | |
222 | const struct flash_ops *sc_ops; | 222 | const struct flash_ops *sc_ops; | |
223 | struct flash_type sc_type; | 223 | struct flash_type sc_type; | |
224 | }; | 224 | }; | |
225 | 225 | |||
226 | static int eflash_ebus_match (device_t, cfdata_t, void *); | 226 | static int eflash_ebus_match (device_t, cfdata_t, void *); | |
227 | static void eflash_ebus_attach (device_t, device_t, void *); | 227 | static void eflash_ebus_attach (device_t, device_t, void *); | |
228 | 228 | |||
229 | CFATTACH_DECL_NEW(flash_ebus, sizeof (struct eflash_softc), | 229 | CFATTACH_DECL_NEW(flash_ebus, sizeof (struct eflash_softc), | |
230 | eflash_ebus_match, eflash_ebus_attach, NULL, NULL); | 230 | eflash_ebus_match, eflash_ebus_attach, NULL, NULL); | |
231 | 231 | |||
232 | /* implementation decls */ | 232 | /* implementation decls */ | |
233 | static int flash_identify(struct eflash_softc*); | 233 | static int flash_identify(struct eflash_softc*); | |
234 | static int KBinSector(struct flash_type * SecMap, unsigned int SecNo); | 234 | static int KBinSector(struct flash_type * SecMap, unsigned int SecNo); | |
235 | static uint32_t SectorStart(struct flash_type * SecMap, int SecNo); | 235 | static uint32_t SectorStart(struct flash_type * SecMap, int SecNo); | |
236 | static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset); | 236 | static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset); | |
237 | static void eflash_thread(void *arg); | 237 | static void eflash_thread(void *arg); | |
238 | static int eflash_read_at (struct eflash_softc *sc, daddr_t start_sector, char *buffer, | 238 | static int eflash_read_at (struct eflash_softc *sc, daddr_t start_sector, char *buffer, | |
239 | size_t nblocks, size_t * pSizeRead); | 239 | size_t nblocks, size_t * pSizeRead); | |
240 | static int eflash_write_at(struct eflash_softc *sc, daddr_t start_sector, char *buffer, | 240 | static int eflash_write_at(struct eflash_softc *sc, daddr_t start_sector, char *buffer, | |
241 | size_t nblocks, size_t * pSizeWritten); | 241 | size_t nblocks, size_t * pSizeWritten); | |
242 | 242 | |||
243 | /* Config functions | 243 | /* Config functions | |
244 | */ | 244 | */ | |
245 | static int | 245 | static int | |
246 | eflash_ebus_match(device_t parent, cfdata_t match, void *aux) | 246 | eflash_ebus_match(device_t parent, cfdata_t match, void *aux) | |
247 | { | 247 | { | |
248 | struct ebus_attach_args *ia = aux; | 248 | struct ebus_attach_args *ia = aux; | |
249 | struct _Flash *f = (struct _Flash *)ia->ia_vaddr; | 249 | struct _Flash *f = (struct _Flash *)ia->ia_vaddr; | |
250 | 250 | |||
251 | if (strcmp("flash", ia->ia_name) != 0) | 251 | if (strcmp("flash", ia->ia_name) != 0) | |
252 | return (0); | 252 | return (0); | |
253 | if ((f == NULL) || | 253 | if ((f == NULL) || | |
254 | ((f->BaseAddressAndTag & FLASHBT_TAG) != PMTTAG_FLASH)) | 254 | ((f->BaseAddressAndTag & FLASHBT_TAG) != PMTTAG_FLASH)) | |
255 | return (0); | 255 | return (0); | |
256 | 256 | |||
257 | return (1); | 257 | return (1); | |
258 | } | 258 | } | |
259 | 259 | |||
260 | static void | 260 | static void | |
261 | eflash_ebus_attach(device_t parent, device_t self, void *aux) | 261 | eflash_ebus_attach(device_t parent, device_t self, void *aux) | |
262 | { | 262 | { | |
263 | struct ebus_attach_args *ia =aux; | 263 | struct ebus_attach_args *ia =aux; | |
264 | struct eflash_softc *sc = device_private(self); | 264 | struct eflash_softc *sc = device_private(self); | |
265 | uint32_t base, ctrl; | 265 | uint32_t base, ctrl; | |
266 | int error; | 266 | int error; | |
267 | 267 | |||
268 | /* Plan. | 268 | /* Plan. | |
269 | * - mips_map_physmem() (with uncached) first page | 269 | * - mips_map_physmem() (with uncached) first page | |
270 | * - keep it around since we need status ops | 270 | * - keep it around since we need status ops | |
271 | * - find what type it is. | 271 | * - find what type it is. | |
272 | * - then mips_map_physmem() each sector as needed. | 272 | * - then mips_map_physmem() each sector as needed. | |
273 | */ | 273 | */ | |
274 | 274 | |||
275 | sc->sc_dev = self; | 275 | sc->sc_dev = self; | |
276 | sc->sc_dp = (struct _Flash*)ia->ia_vaddr; | 276 | sc->sc_dp = (struct _Flash*)ia->ia_vaddr; | |
277 | base = sc->sc_dp->BaseAddressAndTag & FLASHBT_BASE; | 277 | base = sc->sc_dp->BaseAddressAndTag & FLASHBT_BASE; | |
278 | ctrl = sc->sc_dp->Control; | 278 | ctrl = sc->sc_dp->Control; | |
279 | 279 | |||
280 | sc->sc_size = ctrl & FLASHST_SIZE; | 280 | sc->sc_size = ctrl & FLASHST_SIZE; | |
281 | sc->sc_capacity = sc->sc_size / DEV_BSIZE; | 281 | sc->sc_capacity = sc->sc_size / DEV_BSIZE; | |
282 | sc->sc_base = base; | 282 | sc->sc_base = base; | |
283 | /* The chip is 16bit, so if we get 32bit there are two */ | 283 | /* The chip is 16bit, so if we get 32bit there are two */ | |
284 | sc->sc_chips = (ctrl & FLASHST_BUS_32) ? 2 : 1; | 284 | sc->sc_chips = (ctrl & FLASHST_BUS_32) ? 2 : 1; | |
285 | 285 | |||
286 | /* Map the first page to see what chip we got */ | 286 | /* Map the first page to see what chip we got */ | |
287 | sc->sc_page0 = (volatile uint8_t *) mips_map_physmem(base, PAGE_SIZE); | 287 | sc->sc_page0 = (volatile uint8_t *) mips_map_physmem(base, PAGE_SIZE); | |
288 | 288 | |||
289 | if (flash_identify(sc)) { | 289 | if (flash_identify(sc)) { | |
290 | printf(" base %x: %dMB flash memory (%d x %s)\n", base, sc->sc_size >> 20, | 290 | printf(" base %x: %dMB flash memory (%d x %s)\n", base, sc->sc_size >> 20, | |
291 | sc->sc_chips, sc->sc_type.ft_name); | 291 | sc->sc_chips, sc->sc_type.ft_name); | |
292 | } else { | 292 | } else { | |
293 | /* BUGBUG If we dont identify it stop the driver! */ | 293 | /* BUGBUG If we dont identify it stop the driver! */ | |
294 | printf(": unknown manufacturer id %x, device id %x\n", | 294 | printf(": unknown manufacturer id %x, device id %x\n", | |
295 | sc->sc_type.ft_manuf_code, sc->sc_type.ft_device_code); | 295 | sc->sc_type.ft_manuf_code, sc->sc_type.ft_device_code); | |
296 | } | 296 | } | |
297 | 297 | |||
298 | config_pending_incr(self); | 298 | config_pending_incr(self); | |
299 | 299 | |||
300 | error = kthread_create(PRI_NONE, 0, NULL, | 300 | error = kthread_create(PRI_NONE, 0, NULL, | |
301 | eflash_thread, sc, NULL, "%s", device_xname(sc->sc_dev)); | 301 | eflash_thread, sc, NULL, "%s", device_xname(sc->sc_dev)); | |
302 | if (error) | 302 | if (error) | |
303 | aprint_error_dev(sc->sc_dev, | 303 | aprint_error_dev(sc->sc_dev, | |
304 | "unable to create kernel thread: error %d\n", error); | 304 | "unable to create kernel thread: error %d\n", error); | |
305 | } | 305 | } | |
306 | 306 | |||
307 | /* Implementation functions | 307 | /* Implementation functions | |
308 | */ | 308 | */ | |
309 | /* Returns the size in KBytes of a given sector, | 309 | /* Returns the size in KBytes of a given sector, | |
310 | * or -1 for bad arguments. | 310 | * or -1 for bad arguments. | |
311 | */ | 311 | */ | |
312 | static int KBinSector(struct flash_type * SecMap, unsigned int SecNo) | 312 | static int KBinSector(struct flash_type * SecMap, unsigned int SecNo) | |
313 | { | 313 | { | |
314 | int i; | 314 | int i; | |
315 | 315 | |||
316 | for (i = 0; i < nDELTAS; i++) { | 316 | for (i = 0; i < nDELTAS; i++) { | |
317 | if (SecNo < SecMap->ft_deltas[i].nSectors) | 317 | if (SecNo < SecMap->ft_deltas[i].nSectors) | |
318 | return SecMap->ft_deltas[i].nKB; | 318 | return SecMap->ft_deltas[i].nKB; | |
319 | SecNo -= SecMap->ft_deltas[i].nSectors; | 319 | SecNo -= SecMap->ft_deltas[i].nSectors; | |
320 | } | 320 | } | |
321 | 321 | |||
322 | return -1; | 322 | return -1; | |
323 | } | 323 | } | |
324 | 324 | |||
325 | #define SectorSize(_map_,_sector_) (1024 * KBinSector(_map_,_sector_)) | 325 | #define SectorSize(_map_,_sector_) (1024 * KBinSector(_map_,_sector_)) | |
326 | 326 | |||
327 | /* Whats the starting offset of sector N | 327 | /* Whats the starting offset of sector N | |
328 | */ | 328 | */ | |
329 | static uint32_t SectorStart(struct flash_type * SecMap, int SecNo) | 329 | static uint32_t SectorStart(struct flash_type * SecMap, int SecNo) | |
330 | { | 330 | { | |
331 | int i; | 331 | int i; | |
332 | uint32_t Offset = 0; | 332 | uint32_t Offset = 0; | |
333 | 333 | |||
334 | for (i = 0; i < nDELTAS; i++) { | 334 | for (i = 0; i < nDELTAS; i++) { | |
335 | if ((unsigned int)SecNo < SecMap->ft_deltas[i].nSectors) | 335 | if ((unsigned int)SecNo < SecMap->ft_deltas[i].nSectors) | |
336 | return 1024 * (Offset + (SecMap->ft_deltas[i].nKB * SecNo)); | 336 | return 1024 * (Offset + (SecMap->ft_deltas[i].nKB * SecNo)); | |
337 | SecNo -= SecMap->ft_deltas[i].nSectors; | 337 | SecNo -= SecMap->ft_deltas[i].nSectors; | |
338 | Offset += SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB; | 338 | Offset += SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB; | |
339 | } | 339 | } | |
340 | 340 | |||
341 | return ~0; | 341 | return ~0; | |
342 | } | 342 | } | |
343 | 343 | |||
344 | /* What sector number corresponds to a given offset | 344 | /* What sector number corresponds to a given offset | |
345 | */ | 345 | */ | |
346 | static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset) | 346 | static unsigned int SectorNumber(struct flash_type * SecMap, uint32_t Offset) | |
347 | { | 347 | { | |
348 | unsigned int i; | 348 | unsigned int i; | |
349 | unsigned int SecNo = 0; | 349 | unsigned int SecNo = 0; | |
350 | 350 | |||
351 | Offset /= 1024; | 351 | Offset /= 1024; | |
352 | for (i = 0; i < nDELTAS; i++) { | 352 | for (i = 0; i < nDELTAS; i++) { | |
353 | if (Offset < (unsigned int) | 353 | if (Offset < (unsigned int) | |
354 | ((SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB))) | 354 | ((SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB))) | |
355 | return SecNo + (Offset / SecMap->ft_deltas[i].nKB); | 355 | return SecNo + (Offset / SecMap->ft_deltas[i].nKB); | |
356 | SecNo += SecMap->ft_deltas[i].nSectors; | 356 | SecNo += SecMap->ft_deltas[i].nSectors; | |
357 | Offset -= SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB; | 357 | Offset -= SecMap->ft_deltas[i].nSectors * SecMap->ft_deltas[i].nKB; | |
358 | } | 358 | } | |
359 | 359 | |||
360 | return ~0; | 360 | return ~0; | |
361 | } | 361 | } | |
362 | 362 | |||
363 | /* | 363 | /* | |
364 | * Semi-generic operations | 364 | * Semi-generic operations | |
365 | */ | 365 | */ | |
366 | struct flash_ops { | 366 | struct flash_ops { | |
367 | void (*write_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t Value); | 367 | void (*write_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t Value); | |
368 | void (*read_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t *Value); | 368 | void (*read_uint8) (struct eflash_softc *sc, volatile void *Offset, uint8_t *Value); | |
369 | void (*write_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t Value); | 369 | void (*write_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t Value); | |
370 | void (*read_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t *Value); | 370 | void (*read_uint16) (struct eflash_softc *sc, volatile void *Offset, uint16_t *Value); | |
371 | void (*write_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t Value); | 371 | void (*write_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t Value); | |
372 | void (*read_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t *Value); | 372 | void (*read_uint32) (struct eflash_softc *sc, volatile void *Offset, uint32_t *Value); | |
373 | int (*program_word) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues, | 373 | int (*program_word) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues, | |
374 | int Verify, int *nWritten); | 374 | int Verify, int *nWritten); | |
375 | int (*program_buffer) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues, | 375 | int (*program_buffer) (struct eflash_softc *sc, volatile void *Offset, uint16_t *pValues, | |
376 | int Verify, int *nWritten); | 376 | int Verify, int *nWritten); | |
377 | }; | 377 | }; | |
378 | 378 | |||
379 | /* | 379 | /* | |
380 | * Hardware access proper, single-chip | 380 | * Hardware access proper, single-chip | |
381 | */ | 381 | */ | |
382 | static void single_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value) | 382 | static void single_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value) | |
383 | { | 383 | { | |
384 | volatile uint8_t * Where = Offset; | 384 | volatile uint8_t * Where = Offset; | |
385 | *Where = Value; | 385 | *Where = Value; | |
386 | } | 386 | } | |
387 | 387 | |||
388 | static void single_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value) | 388 | static void single_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value) | |
389 | { | 389 | { | |
390 | volatile uint8_t * Where = Offset; | 390 | volatile uint8_t * Where = Offset; | |
391 | *Value = *Where; | 391 | *Value = *Where; | |
392 | } | 392 | } | |
393 | 393 | |||
394 | static void single_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value) | 394 | static void single_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value) | |
395 | { | 395 | { | |
396 | volatile uint16_t * Where = Offset; | 396 | volatile uint16_t * Where = Offset; | |
397 | *Where = Value; | 397 | *Where = Value; | |
398 | } | 398 | } | |
399 | 399 | |||
400 | static void single_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value) | 400 | static void single_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value) | |
401 | { | 401 | { | |
402 | volatile uint16_t * Where = Offset; | 402 | volatile uint16_t * Where = Offset; | |
403 | *Value = *Where; | 403 | *Value = *Where; | |
404 | } | 404 | } | |
405 | 405 | |||
406 | /* This one should not be used, probably */ | 406 | /* This one should not be used, probably */ | |
407 | static void single_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value) | 407 | static void single_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value) | |
408 | { | 408 | { | |
409 | #if 0 | 409 | #if 0 | |
410 | /* The chip cannot take back-to-back writes */ | 410 | /* The chip cannot take back-to-back writes */ | |
411 | volatile uint32_t * Where = Offset; | 411 | volatile uint32_t * Where = Offset; | |
412 | *Where = Value; | 412 | *Where = Value; | |
413 | #else | 413 | #else | |
414 | volatile uint8_t * Where = Offset; | 414 | volatile uint8_t * Where = Offset; | |
415 | uint16_t v0, v1; | 415 | uint16_t v0, v1; | |
416 | 416 | |||
417 | /* Unfortunately, this is bytesex dependent */ | 417 | /* Unfortunately, this is bytesex dependent */ | |
418 | #if (BYTE_ORDER == BIG_ENDIAN) | 418 | #if (BYTE_ORDER == BIG_ENDIAN) | |
419 | v1 = (uint16_t) Value; | 419 | v1 = (uint16_t) Value; | |
420 | v0 = (uint16_t) (Value >> 16); | 420 | v0 = (uint16_t) (Value >> 16); | |
421 | #else | 421 | #else | |
422 | v0 = (uint16_t) Value; | 422 | v0 = (uint16_t) Value; | |
423 | v1 = (uint16_t) (Value >> 16); | 423 | v1 = (uint16_t) (Value >> 16); | |
424 | #endif | 424 | #endif | |
425 | single_write_uint16(sc,Where,v0); | 425 | single_write_uint16(sc,Where,v0); | |
426 | single_write_uint16(sc,Where+2,v1); | 426 | single_write_uint16(sc,Where+2,v1); | |
427 | #endif | 427 | #endif | |
428 | } | 428 | } | |
429 | 429 | |||
430 | static void single_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value) | 430 | static void single_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value) | |
431 | { | 431 | { | |
432 | /* back-to-back reads must be ok */ | 432 | /* back-to-back reads must be ok */ | |
433 | volatile uint32_t * Where = Offset; | 433 | volatile uint32_t * Where = Offset; | |
434 | *Value = *Where; | 434 | *Value = *Where; | |
435 | } | 435 | } | |
436 | 436 | |||
437 | /* | 437 | /* | |
438 | * Hardware access proper, paired-chips | 438 | * Hardware access proper, paired-chips | |
439 | * NB: This set of ops assumes two chips in parallel on a 32bit bus, | 439 | * NB: This set of ops assumes two chips in parallel on a 32bit bus, | |
440 | * each operation is repeated in parallel to both chips | 440 | * each operation is repeated in parallel to both chips | |
441 | */ | 441 | */ | |
442 | static void twin_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value) | 442 | static void twin_write_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t Value) | |
443 | { | 443 | { | |
444 | volatile uint32_t * Where = Offset; | 444 | volatile uint32_t * Where = Offset; | |
445 | uint32_t v = Value | ((uint32_t)Value << 16); | 445 | uint32_t v = Value | ((uint32_t)Value << 16); | |
446 | 446 | |||
447 | v = le32toh(v); | 447 | v = le32toh(v); | |
448 | *Where = v; | 448 | *Where = v; | |
449 | } | 449 | } | |
450 | 450 | |||
451 | static void twin_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value) | 451 | static void twin_read_uint8 (struct eflash_softc *sc,volatile void *Offset,uint8_t *Value) | |
452 | { | 452 | { | |
453 | volatile uint32_t * Where = Offset; | 453 | volatile uint32_t * Where = Offset; | |
454 | uint32_t v; | 454 | uint32_t v; | |
455 | v = *Where; | 455 | v = *Where; | |
456 | v = le32toh(v); | 456 | v = le32toh(v); | |
457 | *Value = (uint8_t) v; | 457 | *Value = (uint8_t) v; | |
458 | } | 458 | } | |
459 | 459 | |||
460 | /* This one should *not* be used, error-prone */ | 460 | /* This one should *not* be used, error-prone */ | |
461 | static void twin_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value) | 461 | static void twin_write_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t Value) | |
462 | { | 462 | { | |
463 | volatile uint16_t * Where = Offset; | 463 | volatile uint16_t * Where = Offset; | |
464 | *Where = Value; | 464 | *Where = Value; | |
465 | } | 465 | } | |
466 | 466 | |||
467 | static void twin_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value) | 467 | static void twin_read_uint16 (struct eflash_softc *sc,volatile void *Offset,uint16_t *Value) | |
468 | { | 468 | { | |
469 | volatile uint16_t * Where = Offset; | 469 | volatile uint16_t * Where = Offset; | |
470 | *Value = *Where; | 470 | *Value = *Where; | |
471 | } | 471 | } | |
472 | 472 | |||
473 | static void twin_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value) | 473 | static void twin_write_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t Value) | |
474 | { | 474 | { | |
475 | volatile uint32_t * Where = Offset; | 475 | volatile uint32_t * Where = Offset; | |
476 | Value = le32toh(Value); | 476 | Value = le32toh(Value); | |
477 | *Where = Value; | 477 | *Where = Value; | |
478 | } | 478 | } | |
479 | 479 | |||
480 | static void twin_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value) | 480 | static void twin_read_uint32 (struct eflash_softc *sc,volatile void *Offset,uint32_t *Value) | |
481 | { | 481 | { | |
482 | volatile uint32_t * Where = Offset; | 482 | volatile uint32_t * Where = Offset; | |
483 | uint32_t v; | 483 | uint32_t v; | |
484 | v = *Where; | 484 | v = *Where; | |
485 | v = le32toh(v); | 485 | v = le32toh(v); | |
486 | *Value = v; | 486 | *Value = v; | |
487 | } | 487 | } | |
488 | 488 | |||
489 | /* | 489 | /* | |
490 | * Command and status definitions | 490 | * Command and status definitions | |
491 | */ | 491 | */ | |
492 | 492 | |||
493 | /* Defines for the STATUS register | 493 | /* Defines for the STATUS register | |
494 | */ | 494 | */ | |
495 | #define ST_reserved 0x01 | 495 | #define ST_reserved 0x01 | |
496 | #define ST_BLOCK_LOCKED 0x02 | 496 | #define ST_BLOCK_LOCKED 0x02 | |
497 | #define ST_PROGRAM_SUSPENDED 0x04 | 497 | #define ST_PROGRAM_SUSPENDED 0x04 | |
498 | #define ST_LOW_VOLTAGE 0x08 | 498 | #define ST_LOW_VOLTAGE 0x08 | |
499 | #define ST_LOCK_BIT_ERROR 0x10 | 499 | #define ST_LOCK_BIT_ERROR 0x10 | |
500 | #define ST_ERASE_ERROR 0x20 | 500 | #define ST_ERASE_ERROR 0x20 | |
501 | #define ST_ERASE_SUSPENDED 0x40 | 501 | #define ST_ERASE_SUSPENDED 0x40 | |
502 | #define ST_READY 0x80 | 502 | #define ST_READY 0x80 | |
503 | #define ST_ERASE_MASK 0xee /* bits to check after erase command */ | 503 | #define ST_ERASE_MASK 0xee /* bits to check after erase command */ | |
504 | #define ST_MASK 0xfe /* ignore reserved */ | 504 | #define ST_MASK 0xfe /* ignore reserved */ | |
505 | 505 | |||
506 | /* Command set (what we use of it) | 506 | /* Command set (what we use of it) | |
507 | */ | 507 | */ | |
508 | #define CMD_CONFIRM 0xd0 | 508 | #define CMD_CONFIRM 0xd0 | |
509 | #define CMD_READ_ARRAY 0xff | 509 | #define CMD_READ_ARRAY 0xff | |
510 | #define CMD_READ_ID 0x90 | 510 | #define CMD_READ_ID 0x90 | |
511 | #define CMD_READ_STATUS 0x70 | 511 | #define CMD_READ_STATUS 0x70 | |
512 | #define CMD_CLEAR_STATUS 0x50 | 512 | #define CMD_CLEAR_STATUS 0x50 | |
513 | #define CMD_WRITE_WORD 0x40 | 513 | #define CMD_WRITE_WORD 0x40 | |
514 | #define CMD_WRITE_BUFFER 0xe8 | 514 | #define CMD_WRITE_BUFFER 0xe8 | |
515 | #define CMD_ERASE_SETUP 0x20 | 515 | #define CMD_ERASE_SETUP 0x20 | |
516 | #define CMD_ERASE_CONFIRM CMD_CONFIRM | 516 | #define CMD_ERASE_CONFIRM CMD_CONFIRM | |
517 | #define CMD_SET_PREFIX 0x60 /* set read config, lock bits */ | 517 | #define CMD_SET_PREFIX 0x60 /* set read config, lock bits */ | |
518 | #define CMD_LOCK 0x01 | 518 | #define CMD_LOCK 0x01 | |
519 | #define CMD_UNLOCK CMD_CONFIRM | 519 | #define CMD_UNLOCK CMD_CONFIRM | |
520 | /* What we dont use of it | 520 | /* What we dont use of it | |
521 | */ | 521 | */ | |
522 | #define CMD_READ_QUERY 0x98 | 522 | #define CMD_READ_QUERY 0x98 | |
523 | # define BUFFER_BYTES 32 | 523 | # define BUFFER_BYTES 32 | |
524 | #define CMD_ERASE_SUSPEND 0xb0 | 524 | #define CMD_ERASE_SUSPEND 0xb0 | |
525 | #define CMD_ERASE_RESUME CMD_CONFIRM | 525 | #define CMD_ERASE_RESUME CMD_CONFIRM | |
526 | #define CMD_CONFIGURATION 0xb8 | 526 | #define CMD_CONFIGURATION 0xb8 | |
527 | #define CMD_PROTECT 0xc0 | 527 | #define CMD_PROTECT 0xc0 | |
528 | 528 | |||
529 | /* Enter the Product ID mode (Read Identifier Codes) | 529 | /* Enter the Product ID mode (Read Identifier Codes) | |
530 | */ | 530 | */ | |
531 | static void ProductIdEnter(struct eflash_softc *sc) | 531 | static void ProductIdEnter(struct eflash_softc *sc) | |
532 | { | 532 | { | |
533 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ID); | 533 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ID); | |
534 | } | 534 | } | |
535 | 535 | |||
536 | /* Exit the Product ID mode (enter Read Array mode) | 536 | /* Exit the Product ID mode (enter Read Array mode) | |
537 | */ | 537 | */ | |
538 | static void ProductIdExit(struct eflash_softc *sc) | 538 | static void ProductIdExit(struct eflash_softc *sc) | |
539 | { | 539 | { | |
540 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY); | 540 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY); | |
541 | } | 541 | } | |
542 | 542 | |||
543 | /* Read the status register | 543 | /* Read the status register | |
544 | */ | 544 | */ | |
545 | static uint8_t ReadStatusRegister(struct eflash_softc *sc) | 545 | static uint8_t ReadStatusRegister(struct eflash_softc *sc) | |
546 | { | 546 | { | |
547 | uint8_t Status; | 547 | uint8_t Status; | |
548 | 548 | |||
549 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_STATUS); | 549 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_STATUS); | |
550 | sc->sc_ops->read_uint8(sc,sc->sc_page0,&Status); | 550 | sc->sc_ops->read_uint8(sc,sc->sc_page0,&Status); | |
551 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY); | 551 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_READ_ARRAY); | |
552 | return Status; | 552 | return Status; | |
553 | } | 553 | } | |
554 | 554 | |||
555 | /* Clear error bits in status | 555 | /* Clear error bits in status | |
556 | */ | 556 | */ | |
557 | static void ClearStatusRegister(struct eflash_softc *sc) | 557 | static void ClearStatusRegister(struct eflash_softc *sc) | |
558 | { | 558 | { | |
559 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_CLEAR_STATUS); | 559 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_CLEAR_STATUS); | |
560 | } | 560 | } | |
561 | 561 | |||
562 | #if DEBUG | 562 | #if DEBUG | |
563 | /* Decode status bits | 563 | /* Decode status bits | |
564 | */ | 564 | */ | |
565 | typedef const char *string; | 565 | typedef const char *string; | |
566 | 566 | |||
567 | static void PrintStatus(uint8_t Status) | 567 | static void PrintStatus(uint8_t Status) | |
568 | { | 568 | { | |
569 | /* BUGBUG there's a %b format I think? */ | 569 | /* BUGBUG there's a %b format I think? */ | |
570 | string BitNames[8] = { | 570 | string BitNames[8] = { | |
571 | "reserved", "BLOCK_LOCKED", | 571 | "reserved", "BLOCK_LOCKED", | |
572 | "PROGRAM_SUSPENDED", "LOW_VOLTAGE", | 572 | "PROGRAM_SUSPENDED", "LOW_VOLTAGE", | |
573 | "LOCK_BIT_ERROR", "ERASE_ERROR", | 573 | "LOCK_BIT_ERROR", "ERASE_ERROR", | |
574 | "ERASE_SUSPENDED", "READY" | 574 | "ERASE_SUSPENDED", "READY" | |
575 | }; | 575 | }; | |
576 | int i; | 576 | int i; | |
577 | int OneSet = FALSE; | 577 | int OneSet = FALSE; | |
578 | 578 | |||
579 | printf("[status %x =",Status); | 579 | printf("[status %x =",Status); | |
580 | for (i = 0; i < 8; i++) { | 580 | for (i = 0; i < 8; i++) { | |
581 | if (Status & (1<<i)) { | 581 | if (Status & (1<<i)) { | |
582 | printf("%c%s", | 582 | printf("%c%s", | |
583 | (OneSet) ? '|' : ' ', | 583 | (OneSet) ? '|' : ' ', | |
584 | BitNames[i]); | 584 | BitNames[i]); | |
585 | OneSet = TRUE; | 585 | OneSet = TRUE; | |
586 | } | 586 | } | |
587 | } | 587 | } | |
588 | printf("]\n"); | 588 | printf("]\n"); | |
589 | } | 589 | } | |
590 | #else | 590 | #else | |
591 | #define PrintStatus(x) | 591 | #define PrintStatus(x) | |
592 | #endif | 592 | #endif | |
593 | 593 | |||
594 | /* | 594 | /* | |
595 | * The device can lock up under certain conditions. | 595 | * The device can lock up under certain conditions. | |
596 | * There is no software workaround [must toggle RP# to GND] | 596 | * There is no software workaround [must toggle RP# to GND] | |
597 | * Check if it seems that we are in that state. | 597 | * Check if it seems that we are in that state. | |
598 | */ | 598 | */ | |
599 | static int IsIrresponsive(struct eflash_softc *sc) | 599 | static int IsIrresponsive(struct eflash_softc *sc) | |
600 | { | 600 | { | |
601 | uint8_t Status = ReadStatusRegister(sc); | 601 | uint8_t Status = ReadStatusRegister(sc); | |
602 | 602 | |||
603 | if (Status & ST_READY) | 603 | if (Status & ST_READY) | |
604 | return FALSE; | 604 | return FALSE; | |
605 | 605 | |||
606 | if ((Status & ST_MASK) == | 606 | if ((Status & ST_MASK) == | |
607 | (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) { | 607 | (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) { | |
608 | /* yes, looks that way */ | 608 | /* yes, looks that way */ | |
609 | return TRUE; | 609 | return TRUE; | |
610 | } | 610 | } | |
611 | 611 | |||
612 | /* Something is indeed amiss, but we dont really know for sure */ | 612 | /* Something is indeed amiss, but we dont really know for sure */ | |
613 | PrintStatus(ReadStatusRegister(sc)); | 613 | PrintStatus(ReadStatusRegister(sc)); | |
614 | ClearStatusRegister(sc); | 614 | ClearStatusRegister(sc); | |
615 | PrintStatus(ReadStatusRegister(sc)); | 615 | PrintStatus(ReadStatusRegister(sc)); | |
616 | 616 | |||
617 | if ((Status & ST_MASK) == | 617 | if ((Status & ST_MASK) == | |
618 | (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) { | 618 | (ST_LOCK_BIT_ERROR|ST_ERASE_SUSPENDED|ST_ERASE_ERROR)) { | |
619 | /* yes, looks that way */ | 619 | /* yes, looks that way */ | |
620 | return TRUE; | 620 | return TRUE; | |
621 | } | 621 | } | |
622 | 622 | |||
623 | return FALSE; | 623 | return FALSE; | |
624 | } | 624 | } | |
625 | 625 | |||
626 | 626 | |||
627 | /* Write one 16bit word | 627 | /* Write one 16bit word | |
628 | */ | 628 | */ | |
629 | static int | 629 | static int | |
630 | single_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | 630 | single_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | |
631 | int Verify, int *nWritten) | 631 | int Verify, int *nWritten) | |
632 | { | 632 | { | |
633 | uint8_t Status; | 633 | uint8_t Status; | |
634 | uint16_t i, Data16, Value; | 634 | uint16_t i, Data16, Value; | |
635 | 635 | |||
636 | *nWritten = 0; | 636 | *nWritten = 0; | |
637 | 637 | |||
638 | Value = Values[0]; | 638 | Value = Values[0]; | |
639 | 639 | |||
640 | if (Verify) { | 640 | if (Verify) { | |
641 | sc->sc_ops->read_uint16(sc,Offset,&Data16); | 641 | sc->sc_ops->read_uint16(sc,Offset,&Data16); | |
642 | #ifdef Verbose | 642 | #ifdef Verbose | |
643 | if (Verbose) { | 643 | if (Verbose) { | |
644 | printf("Location %p was x%x\n", | 644 | printf("Location %p was x%x\n", | |
645 | Offset, Data16); | 645 | Offset, Data16); | |
646 | } | 646 | } | |
647 | #endif | 647 | #endif | |
648 | if (Data16 != 0xffff) | 648 | if (Data16 != 0xffff) | |
649 | printf("Offset %p not ERASED, wont take.\n",Offset); | 649 | printf("Offset %p not ERASED, wont take.\n",Offset); | |
650 | } | 650 | } | |
651 | 651 | |||
652 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD); | 652 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD); | |
653 | sc->sc_ops->write_uint16(sc,Offset,Value); | 653 | sc->sc_ops->write_uint16(sc,Offset,Value); | |
654 | 654 | |||
655 | /* Wait until the operation is completed | 655 | /* Wait until the operation is completed | |
656 | * Specs say it takes between 210 and 630 us | 656 | * Specs say it takes between 210 and 630 us | |
657 | * Errata says 360 TYP and Max=TBD (sic) | 657 | * Errata says 360 TYP and Max=TBD (sic) | |
658 | */ | 658 | */ | |
659 | DELAY(800); | 659 | DELAY(800); | |
660 | 660 | |||
661 | for (i = 0; i < 10; i++) { | 661 | for (i = 0; i < 10; i++) { | |
662 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 662 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
663 | if ((Status & ST_READY)) break; | 663 | if ((Status & ST_READY)) break; | |
664 | DELAY(100); | 664 | DELAY(100); | |
665 | } | 665 | } | |
666 | 666 | |||
667 | ProductIdExit(sc); | 667 | ProductIdExit(sc); | |
668 | 668 | |||
669 | if (Verify) { | 669 | if (Verify) { | |
670 | sc->sc_ops->read_uint16(sc,Offset,&Data16); | 670 | sc->sc_ops->read_uint16(sc,Offset,&Data16); | |
671 | #ifdef Verbose | 671 | #ifdef Verbose | |
672 | if (Verbose) { | 672 | if (Verbose) { | |
673 | printf("Location %p is now x%x\n", | 673 | printf("Location %p is now x%x\n", | |
674 | Offset, Data16); | 674 | Offset, Data16); | |
675 | } | 675 | } | |
676 | #endif | 676 | #endif | |
677 | if ((Data16 != Value)) { | 677 | if ((Data16 != Value)) { | |
678 | PrintStatus(Status); | 678 | PrintStatus(Status); | |
679 | printf(". That didnt work, try again.. [%x != %x]\n", | 679 | printf(". That didnt work, try again.. [%x != %x]\n", | |
680 | Data16, Value); | 680 | Data16, Value); | |
681 | ClearStatusRegister(sc); | 681 | ClearStatusRegister(sc); | |
682 | return FALSE; | 682 | return FALSE; | |
683 | } | 683 | } | |
684 | } | 684 | } | |
685 | 685 | |||
686 | *nWritten = 2; | 686 | *nWritten = 2; | |
687 | return TRUE; | 687 | return TRUE; | |
688 | } | 688 | } | |
689 | 689 | |||
690 | /* Write one buffer, 16bit words at a time | 690 | /* Write one buffer, 16bit words at a time | |
691 | */ | 691 | */ | |
692 | static int | 692 | static int | |
693 | single_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | 693 | single_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | |
694 | int Verify, int *nWritten) | 694 | int Verify, int *nWritten) | |
695 | { | 695 | { | |
696 | uint8_t Status; | 696 | uint8_t Status; | |
697 | uint16_t i, Data16, Value = 0; | 697 | uint16_t i, Data16, Value = 0; | |
698 | volatile uint8_t *Where = Offset; | 698 | volatile uint8_t *Where = Offset; | |
699 | 699 | |||
700 | *nWritten = 0; | 700 | *nWritten = 0; | |
701 | if (sc->sc_buffersize == 0) | 701 | if (sc->sc_buffersize == 0) | |
702 | return FALSE; /* sanity */ | 702 | return FALSE; /* sanity */ | |
703 | 703 | |||
704 | if (Verify) { | 704 | if (Verify) { | |
705 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | 705 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | |
706 | sc->sc_ops->read_uint16(sc,Where+i,&Data16); | 706 | sc->sc_ops->read_uint16(sc,Where+i,&Data16); | |
707 | #ifdef Verbose | 707 | #ifdef Verbose | |
708 | if (Verbose) { | 708 | if (Verbose) { | |
709 | printf("Location %p was x%x\n", | 709 | printf("Location %p was x%x\n", | |
710 | Where+i, Data16); | 710 | Where+i, Data16); | |
711 | } | 711 | } | |
712 | #endif | 712 | #endif | |
713 | 713 | |||
714 | if (Data16 != 0xffff) | 714 | if (Data16 != 0xffff) | |
715 | printf("Offset %p not ERASED, wont take.\n",Where+i); | 715 | printf("Offset %p not ERASED, wont take.\n",Where+i); | |
716 | } | 716 | } | |
717 | } | 717 | } | |
718 | 718 | |||
719 | /* Specs say to retry if necessary */ | 719 | /* Specs say to retry if necessary */ | |
720 | for (i = 0; i < 5; i++) { | 720 | for (i = 0; i < 5; i++) { | |
721 | sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER); | 721 | sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER); | |
722 | DELAY(10); | 722 | DELAY(10); | |
723 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 723 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
724 | if ((Status & ST_READY)) break; | 724 | if ((Status & ST_READY)) break; | |
725 | } | 725 | } | |
726 | if (0 == (Status & ST_READY)) { | 726 | if (0 == (Status & ST_READY)) { | |
727 | printf("FAILED program_buffer at Location %p, Status= x%x\n", | 727 | printf("FAILED program_buffer at Location %p, Status= x%x\n", | |
728 | Offset, Status); | 728 | Offset, Status); | |
729 | return FALSE; | 729 | return FALSE; | |
730 | } | 730 | } | |
731 | 731 | |||
732 | /* Say how many words we'll be sending */ | 732 | /* Say how many words we'll be sending */ | |
733 | sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/2)); | 733 | sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/2)); | |
734 | 734 | |||
735 | /* Send the data */ | 735 | /* Send the data */ | |
736 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | 736 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | |
737 | Value = Values[i/2]; | 737 | Value = Values[i/2]; | |
738 | sc->sc_ops->write_uint16(sc,Where+i,Value); | 738 | sc->sc_ops->write_uint16(sc,Where+i,Value); | |
739 | DELAY(10);/*jic*/ | 739 | DELAY(10);/*jic*/ | |
740 | } | 740 | } | |
741 | 741 | |||
742 | /* Write confirmation */ | 742 | /* Write confirmation */ | |
743 | sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM); | 743 | sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM); | |
744 | 744 | |||
745 | /* Wait until the operation is completed | 745 | /* Wait until the operation is completed | |
746 | * Specs say it takes between 800 and 2400 us | 746 | * Specs say it takes between 800 and 2400 us | |
747 | * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above. | 747 | * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above. | |
748 | */ | 748 | */ | |
749 | DELAY(800); | 749 | DELAY(800); | |
750 | 750 | |||
751 | for (i = 0; i < 20; i++) { | 751 | for (i = 0; i < 20; i++) { | |
752 | sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS); | 752 | sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS); | |
753 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 753 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
754 | if ((Status & ST_READY)) break; | 754 | if ((Status & ST_READY)) break; | |
755 | DELAY(200); | 755 | DELAY(200); | |
756 | } | 756 | } | |
757 | 757 | |||
758 | ProductIdExit(sc); | 758 | ProductIdExit(sc); | |
759 | 759 | |||
760 | /* Verify? */ | 760 | /* Verify? */ | |
761 | if (Verify) { | 761 | if (Verify) { | |
762 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | 762 | for (i = 0; i < sc->sc_buffersize; i+= 2) { | |
763 | sc->sc_ops->read_uint16(sc,Where+i,&Data16); | 763 | sc->sc_ops->read_uint16(sc,Where+i,&Data16); | |
764 | #ifdef Verbose | 764 | #ifdef Verbose | |
765 | if (Verbose) { | 765 | if (Verbose) { | |
766 | printf("Location %p is now x%x\n", | 766 | printf("Location %p is now x%x\n", | |
767 | Where+i, Data16); | 767 | Where+i, Data16); | |
768 | } | 768 | } | |
769 | #endif | 769 | #endif | |
770 | Value = Values[i/2]; | 770 | Value = Values[i/2]; | |
771 | 771 | |||
772 | if ((Data16 != Value)) { | 772 | if ((Data16 != Value)) { | |
773 | PrintStatus(Status); | 773 | PrintStatus(Status); | |
774 | printf(". That didnt work, try again.. [%x != %x]\n", | 774 | printf(". That didnt work, try again.. [%x != %x]\n", | |
775 | Data16, Value); | 775 | Data16, Value); | |
776 | ClearStatusRegister(sc); | 776 | ClearStatusRegister(sc); | |
777 | return FALSE; | 777 | return FALSE; | |
778 | } | 778 | } | |
779 | } | 779 | } | |
780 | } | 780 | } | |
781 | 781 | |||
782 | *nWritten = sc->sc_buffersize; | 782 | *nWritten = sc->sc_buffersize; | |
783 | return TRUE; | 783 | return TRUE; | |
784 | } | 784 | } | |
785 | 785 | |||
786 | /* Write one 32bit word | 786 | /* Write one 32bit word | |
787 | */ | 787 | */ | |
788 | static int | 788 | static int | |
789 | twin_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | 789 | twin_program_word(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | |
790 | int Verify, int *nWritten) | 790 | int Verify, int *nWritten) | |
791 | { | 791 | { | |
792 | uint8_t Status; | 792 | uint8_t Status; | |
793 | uint32_t i, Data32, Value; | 793 | uint32_t i, Data32, Value; | |
794 | uint16_t v0, v1; | 794 | uint16_t v0, v1; | |
795 | 795 | |||
796 | *nWritten = 0; | 796 | *nWritten = 0; | |
797 | 797 | |||
798 | v0 = Values[0]; | 798 | v0 = Values[0]; | |
799 | v0 = le16toh(v0); | 799 | v0 = le16toh(v0); | |
800 | v1 = Values[1]; | 800 | v1 = Values[1]; | |
801 | v1 = le16toh(v1); | 801 | v1 = le16toh(v1); | |
802 | Value = v0 | ((uint32_t)v1 << 16); | 802 | Value = v0 | ((uint32_t)v1 << 16); | |
803 | if (Verify) { | 803 | if (Verify) { | |
804 | sc->sc_ops->read_uint32(sc,Offset,&Data32); | 804 | sc->sc_ops->read_uint32(sc,Offset,&Data32); | |
805 | #ifdef Verbose | 805 | #ifdef Verbose | |
806 | if (Verbose) { | 806 | if (Verbose) { | |
807 | printf("Location %p was x%x\n", | 807 | printf("Location %p was x%x\n", | |
808 | Offset, Data32); | 808 | Offset, Data32); | |
809 | } | 809 | } | |
810 | #endif | 810 | #endif | |
811 | if (Data32 != 0xffffffff) | 811 | if (Data32 != 0xffffffff) | |
812 | printf("Offset %p not ERASED, wont take.\n",Offset); | 812 | printf("Offset %p not ERASED, wont take.\n",Offset); | |
813 | } | 813 | } | |
814 | 814 | |||
815 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD); | 815 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_WRITE_WORD); | |
816 | sc->sc_ops->write_uint32(sc,Offset,Value); | 816 | sc->sc_ops->write_uint32(sc,Offset,Value); | |
817 | 817 | |||
818 | /* Wait until the operation is completed | 818 | /* Wait until the operation is completed | |
819 | * Specs say it takes between 210 and 630 us | 819 | * Specs say it takes between 210 and 630 us | |
820 | * Errata says 360 TYP and Max=TBD (sic) | 820 | * Errata says 360 TYP and Max=TBD (sic) | |
821 | */ | 821 | */ | |
822 | DELAY(400); | 822 | DELAY(400); | |
823 | 823 | |||
824 | for (i = 0; i < 10; i++) { | 824 | for (i = 0; i < 10; i++) { | |
825 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 825 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
826 | if ((Status & ST_READY)) break; | 826 | if ((Status & ST_READY)) break; | |
827 | DELAY(100); | 827 | DELAY(100); | |
828 | } | 828 | } | |
829 | 829 | |||
830 | ProductIdExit(sc); | 830 | ProductIdExit(sc); | |
831 | 831 | |||
832 | if (Verify) { | 832 | if (Verify) { | |
833 | sc->sc_ops->read_uint32(sc,Offset,&Data32); | 833 | sc->sc_ops->read_uint32(sc,Offset,&Data32); | |
834 | #ifdef Verbose | 834 | #ifdef Verbose | |
835 | if (Verbose) { | 835 | if (Verbose) { | |
836 | printf("Location %p is now x%x\n", | 836 | printf("Location %p is now x%x\n", | |
837 | Offset, Data32); | 837 | Offset, Data32); | |
838 | } | 838 | } | |
839 | #endif | 839 | #endif | |
840 | if ((Data32 != Value)) { | 840 | if ((Data32 != Value)) { | |
841 | PrintStatus(Status); | 841 | PrintStatus(Status); | |
842 | printf(". That didnt work, try again.. [%x != %x]\n", | 842 | printf(". That didnt work, try again.. [%x != %x]\n", | |
843 | Data32, Value); | 843 | Data32, Value); | |
844 | ClearStatusRegister(sc); | 844 | ClearStatusRegister(sc); | |
845 | return FALSE; | 845 | return FALSE; | |
846 | } | 846 | } | |
847 | } | 847 | } | |
848 | 848 | |||
849 | *nWritten = 4; | 849 | *nWritten = 4; | |
850 | return TRUE; | 850 | return TRUE; | |
851 | } | 851 | } | |
852 | 852 | |||
853 | /* Write one buffer, 32bit words at a time | 853 | /* Write one buffer, 32bit words at a time | |
854 | */ | 854 | */ | |
855 | static int | 855 | static int | |
856 | twin_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | 856 | twin_program_buffer(struct eflash_softc *sc, volatile void *Offset, uint16_t *Values, | |
857 | int Verify, int *nWritten) | 857 | int Verify, int *nWritten) | |
858 | { | 858 | { | |
859 | uint8_t Status; | 859 | uint8_t Status; | |
860 | uint32_t i, Data32, Value; | 860 | uint32_t i, Data32, Value; | |
861 | uint16_t v0 = 0, v1; | 861 | uint16_t v0 = 0, v1; | |
862 | volatile uint8_t *Where = Offset; | 862 | volatile uint8_t *Where = Offset; | |
863 | 863 | |||
864 | *nWritten = 0; | 864 | *nWritten = 0; | |
865 | if (sc->sc_buffersize == 0) | 865 | if (sc->sc_buffersize == 0) | |
866 | return FALSE; /* sanity */ | 866 | return FALSE; /* sanity */ | |
867 | 867 | |||
868 | if (Verify) { | 868 | if (Verify) { | |
869 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | 869 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | |
870 | sc->sc_ops->read_uint32(sc,Where+i,&Data32); | 870 | sc->sc_ops->read_uint32(sc,Where+i,&Data32); | |
871 | #ifdef Verbose | 871 | #ifdef Verbose | |
872 | if (Verbose) { | 872 | if (Verbose) { | |
873 | printf("Location %p was x%x\n", | 873 | printf("Location %p was x%x\n", | |
874 | Where+i, Data32); | 874 | Where+i, Data32); | |
875 | } | 875 | } | |
876 | #endif | 876 | #endif | |
877 | if (Data32 != 0xffffffff) | 877 | if (Data32 != 0xffffffff) | |
878 | printf("Offset %p not ERASED, wont take.\n",Where+i); | 878 | printf("Offset %p not ERASED, wont take.\n",Where+i); | |
879 | } | 879 | } | |
880 | } | 880 | } | |
881 | 881 | |||
882 | /* Specs say to retry if necessary */ | 882 | /* Specs say to retry if necessary */ | |
883 | for (i = 0; i < 5; i++) { | 883 | for (i = 0; i < 5; i++) { | |
884 | sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER); | 884 | sc->sc_ops->write_uint8(sc,Offset,CMD_WRITE_BUFFER); | |
885 | DELAY(10); | 885 | DELAY(10); | |
886 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 886 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
887 | if ((Status & ST_READY)) break; | 887 | if ((Status & ST_READY)) break; | |
888 | } | 888 | } | |
889 | if (0 == (Status & ST_READY)) { | 889 | if (0 == (Status & ST_READY)) { | |
890 | printf("FAILED program_buffer at Location %p, Status= x%x\n", | 890 | printf("FAILED program_buffer at Location %p, Status= x%x\n", | |
891 | Offset, Status); | 891 | Offset, Status); | |
892 | return FALSE; | 892 | return FALSE; | |
893 | } | 893 | } | |
894 | 894 | |||
895 | /* Say how many words we'll be sending */ | 895 | /* Say how many words we'll be sending */ | |
896 | sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/4)); /* to each twin! */ | 896 | sc->sc_ops->write_uint8(sc,Offset,(uint8_t)(sc->sc_buffersize/4)); /* to each twin! */ | |
897 | 897 | |||
898 | /* Send the data */ | 898 | /* Send the data */ | |
899 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | 899 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | |
900 | v0 = Values[i/2]; | 900 | v0 = Values[i/2]; | |
901 | v0 = le16toh(v0); | 901 | v0 = le16toh(v0); | |
902 | v1 = Values[1+(i/2)]; | 902 | v1 = Values[1+(i/2)]; | |
903 | v1 = le16toh(v1); | 903 | v1 = le16toh(v1); | |
904 | Value = v0 | ((uint32_t)v1 << 16); | 904 | Value = v0 | ((uint32_t)v1 << 16); | |
905 | sc->sc_ops->write_uint32(sc,Where+i,Value); | 905 | sc->sc_ops->write_uint32(sc,Where+i,Value); | |
906 | DELAY(10);/*jic*/ | 906 | DELAY(10);/*jic*/ | |
907 | } | 907 | } | |
908 | 908 | |||
909 | /* Write confirmation */ | 909 | /* Write confirmation */ | |
910 | sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM); | 910 | sc->sc_ops->write_uint8(sc,Offset,CMD_CONFIRM); | |
911 | 911 | |||
912 | /* Wait until the operation is completed | 912 | /* Wait until the operation is completed | |
913 | * Specs say it takes between 800 and 2400 us | 913 | * Specs say it takes between 800 and 2400 us | |
914 | * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above. | 914 | * Errata says 1600 TYP and Max=TBD (sic), but fixed in stepping A3 and above. | |
915 | */ | 915 | */ | |
916 | DELAY(800); | 916 | DELAY(800); | |
917 | 917 | |||
918 | for (i = 0; i < 20; i++) { | 918 | for (i = 0; i < 20; i++) { | |
919 | sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS); | 919 | sc->sc_ops->write_uint8(sc,Offset,CMD_READ_STATUS); | |
920 | sc->sc_ops->read_uint8(sc,Offset,&Status); | 920 | sc->sc_ops->read_uint8(sc,Offset,&Status); | |
921 | if ((Status & ST_READY)) break; | 921 | if ((Status & ST_READY)) break; | |
922 | DELAY(200); | 922 | DELAY(200); | |
923 | } | 923 | } | |
924 | 924 | |||
925 | ProductIdExit(sc); | 925 | ProductIdExit(sc); | |
926 | 926 | |||
927 | /* Verify */ | 927 | /* Verify */ | |
928 | if (Verify) { | 928 | if (Verify) { | |
929 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | 929 | for (i = 0; i < sc->sc_buffersize; i+= 4) { | |
930 | sc->sc_ops->read_uint32(sc,Where+i,&Data32); | 930 | sc->sc_ops->read_uint32(sc,Where+i,&Data32); | |
931 | #ifdef Verbose | 931 | #ifdef Verbose | |
932 | if (Verbose) { | 932 | if (Verbose) { | |
933 | printf("Location %p is now x%x\n", | 933 | printf("Location %p is now x%x\n", | |
934 | Where+i, Data32); | 934 | Where+i, Data32); | |
935 | } | 935 | } | |
936 | #endif | 936 | #endif | |
937 | v0 = Values[i/2]; | 937 | v0 = Values[i/2]; | |
938 | v0 = le16toh(v0); | 938 | v0 = le16toh(v0); | |
939 | v1 = Values[1+(i/2)]; | 939 | v1 = Values[1+(i/2)]; | |
940 | v1 = le16toh(v1); | 940 | v1 = le16toh(v1); | |
941 | Value = v0 | ((uint32_t)v1 << 16); | 941 | Value = v0 | ((uint32_t)v1 << 16); | |
942 | 942 | |||
943 | if ((Data32 != Value)) { | 943 | if ((Data32 != Value)) { | |
944 | PrintStatus(Status); | 944 | PrintStatus(Status); | |
945 | printf(". That didnt work, try again.. [%x != %x]\n", | 945 | printf(". That didnt work, try again.. [%x != %x]\n", | |
946 | Data32, Value); | 946 | Data32, Value); | |
947 | ClearStatusRegister(sc); | 947 | ClearStatusRegister(sc); | |
948 | return FALSE; | 948 | return FALSE; | |
949 | } | 949 | } | |
950 | } | 950 | } | |
951 | } | 951 | } | |
952 | 952 | |||
953 | *nWritten = sc->sc_buffersize; | 953 | *nWritten = sc->sc_buffersize; | |
954 | return TRUE; | 954 | return TRUE; | |
955 | } | 955 | } | |
956 | 956 | |||
957 | /* Is there a lock on a given sector | 957 | /* Is there a lock on a given sector | |
958 | */ | 958 | */ | |
959 | static int IsSectorLocked(struct eflash_softc *sc, uint8_t *secptr) | 959 | static int IsSectorLocked(struct eflash_softc *sc, uint8_t *secptr) | |
960 | { | 960 | { | |
961 | uint8_t Data, Data1; | 961 | uint8_t Data, Data1; | |
962 | 962 | |||
963 | ProductIdEnter(sc); | 963 | ProductIdEnter(sc); | |
964 | /* Lockout info is at address 2 of the given sector, meaning A0=0 A1=1. | 964 | /* Lockout info is at address 2 of the given sector, meaning A0=0 A1=1. | |
965 | */ | 965 | */ | |
966 | sc->sc_ops->read_uint8(sc,secptr+(0x0002*2*sc->sc_chips),&Data); | 966 | sc->sc_ops->read_uint8(sc,secptr+(0x0002*2*sc->sc_chips),&Data); | |
967 | sc->sc_ops->read_uint8(sc,secptr+(0x0003*2*sc->sc_chips),&Data1); | 967 | sc->sc_ops->read_uint8(sc,secptr+(0x0003*2*sc->sc_chips),&Data1); | |
968 | 968 | |||
969 | ProductIdExit(sc); | 969 | ProductIdExit(sc); | |
970 | 970 | |||
971 | return (Data & 1); | 971 | return (Data & 1); | |
972 | } | 972 | } | |
973 | 973 | |||
974 | /* Remove the write-lock to a sector | 974 | /* Remove the write-lock to a sector | |
975 | */ | 975 | */ | |
976 | static void SectorUnLock(struct eflash_softc *sc, uint8_t *secptr) | 976 | static void SectorUnLock(struct eflash_softc *sc, uint8_t *secptr) | |
977 | { | 977 | { | |
978 | uint8_t Status; | 978 | uint8_t Status; | |
979 | int i; | 979 | int i; | |
980 | 980 | |||
981 | DBGME(DEBUG_FUNCS,printf("%s: Unlocking sector %d [ptr %p] ...\n", | 981 | DBGME(DEBUG_FUNCS,printf("%s: Unlocking sector %d [ptr %p] ...\n", | |
982 | device_xname(sc->sc_dev), sc->sc_sector_offset, secptr)); | 982 | device_xname(sc->sc_dev), sc->sc_sector_offset, secptr)); | |
983 | 983 | |||
984 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_SET_PREFIX); | 984 | sc->sc_ops->write_uint8(sc,sc->sc_page0,CMD_SET_PREFIX); | |
985 | sc->sc_ops->write_uint8(sc,secptr,CMD_UNLOCK); | 985 | sc->sc_ops->write_uint8(sc,secptr,CMD_UNLOCK); | |
986 | 986 | |||
987 | /* Wait until the unlock is complete. | 987 | /* Wait until the unlock is complete. | |
988 | * Specs say this takes between 64 and 75 usecs. | 988 | * Specs say this takes between 64 and 75 usecs. | |
989 | */ | 989 | */ | |
990 | DELAY(100); | 990 | DELAY(100); | |
991 | 991 | |||
992 | for (i = 0; i < 10; i++) { | 992 | for (i = 0; i < 10; i++) { | |
993 | sc->sc_ops->read_uint8(sc,secptr,&Status); | 993 | sc->sc_ops->read_uint8(sc,secptr,&Status); | |
994 | if ((Status & ST_READY)) break; | 994 | if ((Status & ST_READY)) break; | |
995 | DELAY(100); | 995 | DELAY(100); | |
996 | } | 996 | } | |
997 | 997 | |||
998 | ProductIdExit(sc); | 998 | ProductIdExit(sc); | |
999 | 999 | |||
1000 | if ((Status & ST_MASK) == ST_READY) { | 1000 | if ((Status & ST_MASK) == ST_READY) { | |
1001 | DBGME(DEBUG_FUNCS,printf("%s: Unlocked ok.\n", | 1001 | DBGME(DEBUG_FUNCS,printf("%s: Unlocked ok.\n", | |
1002 | device_xname(sc->sc_dev))); | 1002 | device_xname(sc->sc_dev))); | |
1003 | return; | 1003 | return; | |
1004 | } | 1004 | } | |
1005 | 1005 | |||
1006 | PrintStatus(Status); | 1006 | PrintStatus(Status); | |
1007 | DBGME(DEBUG_ERRORS,printf("%s: Unlock of sector %d NOT completed (status=%x).\n", | 1007 | DBGME(DEBUG_ERRORS,printf("%s: Unlock of sector %d NOT completed (status=%x).\n", | |
1008 | device_xname(sc->sc_dev), | 1008 | device_xname(sc->sc_dev), | |
1009 | sc->sc_sector_offset, Status)); | 1009 | sc->sc_sector_offset, Status)); | |
1010 | ClearStatusRegister(sc); | 1010 | ClearStatusRegister(sc); | |
1011 | } | 1011 | } | |
1012 | 1012 | |||
1013 | 1013 | |||
1014 | /* Erase one sector | 1014 | /* Erase one sector | |
1015 | */ | 1015 | */ | |
1016 | static int SectorErase(struct eflash_softc *sc, void *secptr) | 1016 | static int SectorErase(struct eflash_softc *sc, void *secptr) | |
1017 | { | 1017 | { | |
1018 | uint8_t Status = 0; | 1018 | uint8_t Status = 0; | |
1019 | uint16_t i; | 1019 | uint16_t i; | |
1020 | 1020 | |||
1021 | DBGME(DEBUG_FUNCS,printf("%s: Erasing sector %d [ptr %p] ...\n", | 1021 | DBGME(DEBUG_FUNCS,printf("%s: Erasing sector %d [ptr %p] ...\n", | |
1022 | device_xname(sc->sc_dev), sc->sc_sector_offset, secptr)); | 1022 | device_xname(sc->sc_dev), sc->sc_sector_offset, secptr)); | |
1023 | 1023 | |||
1024 | /* On some chips we just cannot avoid the locking business. | 1024 | /* On some chips we just cannot avoid the locking business. | |
1025 | */ | 1025 | */ | |
1026 | if ((sc->sc_chips == 1) && | 1026 | if ((sc->sc_chips == 1) && | |
1027 | IsSectorLocked(sc,secptr)) | 1027 | IsSectorLocked(sc,secptr)) | |
1028 | SectorUnLock(sc,secptr); | 1028 | SectorUnLock(sc,secptr); | |
1029 | 1029 | |||
1030 | sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_SETUP); | 1030 | sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_SETUP); | |
1031 | sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_CONFIRM); | 1031 | sc->sc_ops->write_uint8(sc,secptr,CMD_ERASE_CONFIRM); | |
1032 | 1032 | |||
1033 | /* Wait until the erase is actually completed | 1033 | /* Wait until the erase is actually completed | |
1034 | * Specs say it will take between 1 and 5 seconds. | 1034 | * Specs say it will take between 1 and 5 seconds. | |
1035 | * Errata says it takes 2 sec min and 25 sec max. | 1035 | * Errata says it takes 2 sec min and 25 sec max. | |
1036 | * Double that before giving up. | 1036 | * Double that before giving up. | |
1037 | */ | 1037 | */ | |
1038 | for (i = 0; i < 20; i++) { | 1038 | for (i = 0; i < 20; i++) { | |
1039 | /* Sleep for at least 2 seconds | 1039 | /* Sleep for at least 2 seconds | |
1040 | */ | 1040 | */ | |
1041 | tsleep(sc,PWAIT,"erase", hz * 2); | 1041 | tsleep(sc,PWAIT,"erase", hz * 2); | |
1042 | 1042 | |||
1043 | sc->sc_ops->read_uint8(sc,secptr,&Status); | 1043 | sc->sc_ops->read_uint8(sc,secptr,&Status); | |
1044 | if ((Status & ST_READY)) break; | 1044 | if ((Status & ST_READY)) break; | |
1045 | PrintStatus(Status); | 1045 | PrintStatus(Status); | |
1046 | } | 1046 | } | |
1047 | 1047 | |||
1048 | ProductIdExit(sc); | 1048 | ProductIdExit(sc); | |
1049 | 1049 | |||
1050 | if ((Status & ST_ERASE_MASK) == ST_READY) { | 1050 | if ((Status & ST_ERASE_MASK) == ST_READY) { | |
1051 | DBGME(DEBUG_FUNCS,printf("%s: Erased ok.\n", device_xname(sc->sc_dev))); | 1051 | DBGME(DEBUG_FUNCS,printf("%s: Erased ok.\n", device_xname(sc->sc_dev))); | |
1052 | return 0; | 1052 | return 0; | |
1053 | } | 1053 | } | |
1054 | 1054 | |||
1055 | PrintStatus(Status); | 1055 | PrintStatus(Status); | |
1056 | DBGME(DEBUG_ERRORS,printf("%s: Erase of sector %d NOT completed (status=%x).\n", | 1056 | DBGME(DEBUG_ERRORS,printf("%s: Erase of sector %d NOT completed (status=%x).\n", | |
1057 | device_xname(sc->sc_dev), | 1057 | device_xname(sc->sc_dev), | |
1058 | sc->sc_sector_offset, Status)); | 1058 | sc->sc_sector_offset, Status)); | |
1059 | 1059 | |||
1060 | ClearStatusRegister(sc); | 1060 | ClearStatusRegister(sc); | |
1061 | return EIO; | 1061 | return EIO; | |
1062 | } | 1062 | } | |
1063 | 1063 | |||
1064 | 1064 | |||
1065 | 1065 | |||
1066 | /* Write (a portion of) a sector | 1066 | /* Write (a portion of) a sector | |
1067 | */ | 1067 | */ | |
1068 | static size_t eflash_write_sector(struct eflash_softc *sc, char *Buffer, size_t n, | 1068 | static size_t eflash_write_sector(struct eflash_softc *sc, char *Buffer, size_t n, | |
1069 | uint8_t *Offset, int Verify) | 1069 | uint8_t *Offset, int Verify) | |
1070 | { | 1070 | { | |
1071 | size_t i; | 1071 | size_t i; | |
1072 | 1072 | |||
1073 | /* Make sure the device is not screwed up | 1073 | /* Make sure the device is not screwed up | |
1074 | */ | 1074 | */ | |
1075 | if (IsIrresponsive(sc)) { | 1075 | if (IsIrresponsive(sc)) { | |
1076 | printf("FLASH is locked-up (or mapped cacheable?), wont work. "); | 1076 | printf("FLASH is locked-up (or mapped cacheable?), wont work. "); | |
1077 | } | 1077 | } | |
1078 | 1078 | |||
1079 | for (i = 0; i < n;) { | 1079 | for (i = 0; i < n;) { | |
1080 | int nTries; | 1080 | int nTries; | |
1081 | int nWritten = 0;/*we expect 2 or 4 */ | 1081 | int nWritten = 0;/*we expect 2 or 4 */ | |
1082 | 1082 | |||
1083 | if (sc->sc_buffersize && ((n-i) >= sc->sc_buffersize)) { | 1083 | if (sc->sc_buffersize && ((n-i) >= sc->sc_buffersize)) { | |
1084 | for (nTries = 0; nTries < 5; nTries++) | 1084 | for (nTries = 0; nTries < 5; nTries++) | |
1085 | if (sc->sc_ops->program_buffer(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten)) | 1085 | if (sc->sc_ops->program_buffer(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten)) | |
1086 | break; | 1086 | break; | |
1087 | } else { | 1087 | } else { | |
1088 | for (nTries = 0; nTries < 5; nTries++) | 1088 | for (nTries = 0; nTries < 5; nTries++) | |
1089 | if (sc->sc_ops->program_word(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten)) | 1089 | if (sc->sc_ops->program_word(sc,Offset,(uint16_t*)(Buffer+i),Verify,&nWritten)) | |
1090 | break; | 1090 | break; | |
1091 | } | 1091 | } | |
1092 | Offset += nWritten; | 1092 | Offset += nWritten; | |
1093 | i += nWritten; | 1093 | i += nWritten; | |
1094 | if (nWritten == 0) | 1094 | if (nWritten == 0) | |
1095 | break; | 1095 | break; | |
1096 | } | 1096 | } | |
1097 | return i; | 1097 | return i; | |
1098 | } | 1098 | } | |
1099 | 1099 | |||
1100 | /* Identify type and the sector map of the FLASH. | 1100 | /* Identify type and the sector map of the FLASH. | |
1101 | * Argument is the base address of the device and the count of chips on the bus (1/2) | 1101 | * Argument is the base address of the device and the count of chips on the bus (1/2) | |
1102 | * Returns FALSE if failed | 1102 | * Returns FALSE if failed | |
1103 | */ | 1103 | */ | |
1104 | static const struct flash_ops single_ops = { | 1104 | static const struct flash_ops single_ops = { | |
1105 | single_write_uint8, | 1105 | single_write_uint8, | |
1106 | single_read_uint8, | 1106 | single_read_uint8, | |
1107 | single_write_uint16, | 1107 | single_write_uint16, | |
1108 | single_read_uint16, | 1108 | single_read_uint16, | |
1109 | single_write_uint32, | 1109 | single_write_uint32, | |
1110 | single_read_uint32, | 1110 | single_read_uint32, | |
1111 | single_program_word, | 1111 | single_program_word, | |
1112 | single_program_buffer | 1112 | single_program_buffer | |
1113 | }; | 1113 | }; | |
1114 | 1114 | |||
1115 | static const struct flash_ops twin_ops = { | 1115 | static const struct flash_ops twin_ops = { | |
1116 | twin_write_uint8, | 1116 | twin_write_uint8, | |
1117 | twin_read_uint8, | 1117 | twin_read_uint8, | |
1118 | twin_write_uint16, | 1118 | twin_write_uint16, | |
1119 | twin_read_uint16, | 1119 | twin_read_uint16, | |
1120 | twin_write_uint32, | 1120 | twin_write_uint32, | |
1121 | twin_read_uint32, | 1121 | twin_read_uint32, | |
1122 | twin_program_word, | 1122 | twin_program_word, | |
1123 | twin_program_buffer | 1123 | twin_program_buffer | |
1124 | }; | 1124 | }; | |
1125 | 1125 | |||
1126 | static int flash_identify(struct eflash_softc *sc) | 1126 | static int flash_identify(struct eflash_softc *sc) | |
1127 | { | 1127 | { | |
1128 | uint8_t Mid, Did; | 1128 | uint8_t Mid, Did; | |
1129 | int i; | 1129 | int i; | |
1130 | 1130 | |||
1131 | if (sc->sc_chips > 1) | 1131 | if (sc->sc_chips > 1) | |
1132 | sc->sc_ops = &twin_ops; | 1132 | sc->sc_ops = &twin_ops; | |
1133 | else | 1133 | else | |
1134 | sc->sc_ops = &single_ops; | 1134 | sc->sc_ops = &single_ops; | |
1135 | 1135 | |||
1136 | sc->sc_buffersize = 0; | 1136 | sc->sc_buffersize = 0; | |
1137 | #if USE_BUFFERED_WRITES | 1137 | #if USE_BUFFERED_WRITES | |
1138 | sc->sc_buffersize = BUFFER_BYTES * sc->sc_chips; | 1138 | sc->sc_buffersize = BUFFER_BYTES * sc->sc_chips; | |
1139 | #endif | 1139 | #endif | |
1140 | sc->sc_sector = NULL; | 1140 | sc->sc_sector = NULL; | |
1141 | sc->sc_sector_size = 0; | 1141 | sc->sc_sector_size = 0; | |
1142 | sc->sc_sector_offset = NOSECTOR; | 1142 | sc->sc_sector_offset = NOSECTOR; | |
1143 | sc->sc_erased = FALSE; | 1143 | sc->sc_erased = FALSE; | |
1144 | 1144 | |||
1145 | ProductIdEnter(sc); | 1145 | ProductIdEnter(sc); | |
1146 | sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0000*2*sc->sc_chips),&Mid); | 1146 | sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0000*2*sc->sc_chips),&Mid); | |
1147 | sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0001*2*sc->sc_chips),&Did); | 1147 | sc->sc_ops->read_uint8(sc,sc->sc_page0+(0x0001*2*sc->sc_chips),&Did); | |
1148 | ProductIdExit(sc); | 1148 | ProductIdExit(sc); | |
1149 | 1149 | |||
1150 | sc->sc_type.ft_manuf_code = Mid; | 1150 | sc->sc_type.ft_manuf_code = Mid; | |
1151 | sc->sc_type.ft_device_code = Did; | 1151 | sc->sc_type.ft_device_code = Did; | |
1152 | 1152 | |||
1153 | for (i = 0; i < nMAPS; i++) { | 1153 | for (i = 0; i < nMAPS; i++) { | |
1154 | if ((sector_maps[i].ft_manuf_code == Mid) && (sector_maps[i].ft_device_code == Did)) { | 1154 | if ((sector_maps[i].ft_manuf_code == Mid) && (sector_maps[i].ft_device_code == Did)) { | |
1155 | int j; | 1155 | int j; | |
1156 | uint32_t ms = 0; | 1156 | uint32_t ms = 0; | |
1157 | sc->sc_type = sector_maps[i]; | 1157 | sc->sc_type = sector_maps[i]; | |
1158 | /* double the sector sizes if twin-chips */ | 1158 | /* double the sector sizes if twin-chips */ | |
1159 | for (j = 0; j < nDELTAS; j++) { | 1159 | for (j = 0; j < nDELTAS; j++) { | |
1160 | sc->sc_type.ft_deltas[j].nKB *= sc->sc_chips; | 1160 | sc->sc_type.ft_deltas[j].nKB *= sc->sc_chips; | |
1161 | if (ms < sc->sc_type.ft_deltas[j].nKB) | 1161 | if (ms < sc->sc_type.ft_deltas[j].nKB) | |
1162 | ms = sc->sc_type.ft_deltas[j].nKB; | 1162 | ms = sc->sc_type.ft_deltas[j].nKB; | |
1163 | } | 1163 | } | |
1164 | sc->sc_max_secsize = ms * 1024; | 1164 | sc->sc_max_secsize = ms * 1024; | |
1165 | return TRUE; | 1165 | return TRUE; | |
1166 | } | 1166 | } | |
1167 | } | 1167 | } | |
1168 | 1168 | |||
1169 | return FALSE; | 1169 | return FALSE; | |
1170 | } | 1170 | } | |
1171 | 1171 | |||
1172 | /* Common code for read&write argument validation | 1172 | /* Common code for read&write argument validation | |
1173 | */ | 1173 | */ | |
1174 | static int eflash_validate(struct eflash_softc *sc, daddr_t start, size_t *pSize, void **pSrc) | 1174 | static int eflash_validate(struct eflash_softc *sc, daddr_t start, size_t *pSize, void **pSrc) | |
1175 | { | 1175 | { | |
1176 | daddr_t Size; | 1176 | daddr_t Size; | |
1177 | uint32_t sec; | 1177 | uint32_t sec; | |
1178 | size_t secsize, secstart; | 1178 | size_t secsize, secstart; | |
1179 | 1179 | |||
1180 | /* Validate args | 1180 | /* Validate args | |
1181 | */ | 1181 | */ | |
1182 | if (start >= sc->sc_capacity) { | 1182 | if (start >= sc->sc_capacity) { | |
1183 | *pSize = 0; | 1183 | *pSize = 0; | |
1184 | DBGME(DEBUG_ERRORS,printf("eflash::ValidateArg(%qx) EOF\n", start)); | 1184 | DBGME(DEBUG_ERRORS,printf("eflash::ValidateArg(%qx) EOF\n", start)); | |
1185 | return E2BIG; | 1185 | return E2BIG; | |
1186 | } | 1186 | } | |
1187 | 1187 | |||
1188 | /* Map sector if not already | 1188 | /* Map sector if not already | |
1189 | */ | 1189 | */ | |
1190 | sec = SectorNumber(&sc->sc_type, start << DEV_BSHIFT); | 1190 | sec = SectorNumber(&sc->sc_type, start << DEV_BSHIFT); | |
1191 | secsize = SectorSize( &sc->sc_type, sec); | 1191 | secsize = SectorSize( &sc->sc_type, sec); | |
1192 | secstart = SectorStart(&sc->sc_type,sec); | 1192 | secstart = SectorStart(&sc->sc_type,sec); | |
1193 | if (sec != sc->sc_sector_offset) { | 1193 | if (sec != sc->sc_sector_offset) { | |
1194 | int error; | 1194 | int error; | |
1195 | 1195 | |||
1196 | /* unmap previous first */ | 1196 | /* unmap previous first */ | |
1197 | if (sc->sc_sector_offset != NOSECTOR) { | 1197 | if (sc->sc_sector_offset != NOSECTOR) { | |
1198 | DBGME(DEBUG_FUNCS,printf("%s: unmap %p %zx\n", | 1198 | DBGME(DEBUG_FUNCS,printf("%s: unmap %p %zx\n", | |
1199 | device_xname(sc->sc_dev), sc->sc_sector, sc->sc_sector_size)); | 1199 | device_xname(sc->sc_dev), sc->sc_sector, sc->sc_sector_size)); | |
1200 | iounaccess((vaddr_t)sc->sc_sector, sc->sc_sector_size); | 1200 | iounaccess((vaddr_t)sc->sc_sector, sc->sc_sector_size); | |
1201 | sc->sc_sector_offset = NOSECTOR; | 1201 | sc->sc_sector_offset = NOSECTOR; | |
1202 | } | 1202 | } | |
1203 | 1203 | |||
1204 | /* map new */ | 1204 | /* map new */ | |
1205 | error = ioaccess((vaddr_t)sc->sc_sector, | 1205 | error = ioaccess((vaddr_t)sc->sc_sector, | |
1206 | secstart + sc->sc_base, | 1206 | secstart + sc->sc_base, | |
1207 | secsize); | 1207 | secsize); | |
1208 | DBGME(DEBUG_FUNCS,printf("%s: mapped %p %zx -> %zx %d\n", | 1208 | DBGME(DEBUG_FUNCS,printf("%s: mapped %p %zx -> %zx %d\n", | |
1209 | device_xname(sc->sc_dev), | 1209 | device_xname(sc->sc_dev), | |
1210 | sc->sc_sector, secsize, secstart + sc->sc_base,error)); | 1210 | sc->sc_sector, secsize, secstart + sc->sc_base,error)); | |
1211 | if (error) return error; | 1211 | if (error) return error; | |
1212 | 1212 | |||
1213 | /* Update state. We have to assume the sector was not erased. Sigh. */ | 1213 | /* Update state. We have to assume the sector was not erased. Sigh. */ | |
1214 | sc->sc_sector_offset = sec; | 1214 | sc->sc_sector_offset = sec; | |
1215 | sc->sc_sector_size = secsize; | 1215 | sc->sc_sector_size = secsize; | |
1216 | sc->sc_erased = FALSE; | 1216 | sc->sc_erased = FALSE; | |
1217 | } | 1217 | } | |
1218 | 1218 | |||
1219 | /* Adjust size if necessary | 1219 | /* Adjust size if necessary | |
1220 | */ | 1220 | */ | |
1221 | Size = start + *pSize; /* last sector */ | 1221 | Size = start + *pSize; /* last sector */ | |
1222 | if (Size > sc->sc_capacity) { | 1222 | if (Size > sc->sc_capacity) { | |
1223 | /* At most this many sectors | 1223 | /* At most this many sectors | |
1224 | */ | 1224 | */ | |
1225 | Size = sc->sc_capacity - start; | 1225 | Size = sc->sc_capacity - start; | |
1226 | *pSize = (size_t)Size; | 1226 | *pSize = (size_t)Size; | |
1227 | } | 1227 | } | |
1228 | if (*pSize > (secsize >> DEV_BSHIFT)) { | 1228 | if (*pSize > (secsize >> DEV_BSHIFT)) { | |
1229 | *pSize = secsize >> DEV_BSHIFT; | 1229 | *pSize = secsize >> DEV_BSHIFT; | |
1230 | } | 1230 | } | |
1231 | 1231 | |||
1232 | *pSrc = sc->sc_sector + (start << DEV_BSHIFT) - secstart; | 1232 | *pSrc = sc->sc_sector + (start << DEV_BSHIFT) - secstart; | |
1233 | 1233 | |||
1234 | DBGME(DEBUG_FUNCS,printf("%s: Validate %qx %zd %p\n", | 1234 | DBGME(DEBUG_FUNCS,printf("%s: Validate %qx %zd %p\n", | |
1235 | device_xname(sc->sc_dev), start,*pSize, *pSrc)); | 1235 | device_xname(sc->sc_dev), start,*pSize, *pSrc)); | |
1236 | return 0; | 1236 | return 0; | |
1237 | } | 1237 | } | |
1238 | 1238 | |||
1239 | static int eflash_read_at (struct eflash_softc *sc, | 1239 | static int eflash_read_at (struct eflash_softc *sc, | |
1240 | daddr_t start_sector, char *buffer, size_t nblocks, | 1240 | daddr_t start_sector, char *buffer, size_t nblocks, | |
1241 | size_t * pSizeRead) | 1241 | size_t * pSizeRead) | |
1242 | { | 1242 | { | |
1243 | int error; | 1243 | int error; | |
1244 | uint32_t SizeRead = 0; | 1244 | uint32_t SizeRead = 0; | |
1245 | void *src; | 1245 | void *src; | |
1246 | 1246 | |||
1247 | DBGME(DEBUG_XFERS|DEBUG_READS,printf("%s: EflashReadAt(%qx %p %zd %p)\n", | 1247 | DBGME(DEBUG_XFERS|DEBUG_READS,printf("%s: EflashReadAt(%qx %p %zd %p)\n", | |
1248 | device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeRead)); | 1248 | device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeRead)); | |
1249 | 1249 | |||
1250 | /* Validate & trim arguments | 1250 | /* Validate & trim arguments | |
1251 | */ | 1251 | */ | |
1252 | error = eflash_validate(sc, start_sector, &nblocks, &src); | 1252 | error = eflash_validate(sc, start_sector, &nblocks, &src); | |
1253 | 1253 | |||
1254 | /* Copy data if | 1254 | /* Copy data if | |
1255 | */ | 1255 | */ | |
1256 | if (error == 0) { | 1256 | if (error == 0) { | |
1257 | SizeRead = nblocks; | 1257 | SizeRead = nblocks; | |
1258 | memcpy(buffer, src, nblocks << DEV_BSHIFT); | 1258 | memcpy(buffer, src, nblocks << DEV_BSHIFT); | |
1259 | } | 1259 | } | |
1260 | 1260 | |||
1261 | if (pSizeRead) | 1261 | if (pSizeRead) | |
1262 | *pSizeRead = SizeRead; | 1262 | *pSizeRead = SizeRead; | |
1263 | return error; | 1263 | return error; | |
1264 | } | 1264 | } | |
1265 | 1265 | |||
1266 | /* Write SIZE bytes to device. | 1266 | /* Write SIZE bytes to device. | |
1267 | */ | 1267 | */ | |
1268 | static int eflash_write_at (struct eflash_softc *sc, | 1268 | static int eflash_write_at (struct eflash_softc *sc, | |
1269 | daddr_t start_sector, char *buffer, size_t nblocks, | 1269 | daddr_t start_sector, char *buffer, size_t nblocks, | |
1270 | size_t * pSizeWritten) | 1270 | size_t * pSizeWritten) | |
1271 | { | 1271 | { | |
1272 | int error; | 1272 | int error; | |
1273 | void *src; | 1273 | void *src; | |
1274 | size_t SizeWritten = 0; | 1274 | size_t SizeWritten = 0; | |
1275 | 1275 | |||
1276 | DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("%s: EflashWriteAt(%qx %p %zd %p)\n", | 1276 | DBGME(DEBUG_XFERS|DEBUG_WRITES,printf("%s: EflashWriteAt(%qx %p %zd %p)\n", | |
1277 | device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeWritten)); | 1277 | device_xname(sc->sc_dev), start_sector, buffer, nblocks, pSizeWritten)); | |
1278 | 1278 | |||
1279 | /* Validate & trim arguments | 1279 | /* Validate & trim arguments | |
1280 | */ | 1280 | */ | |
1281 | error = eflash_validate(sc, start_sector, &nblocks, &src); | 1281 | error = eflash_validate(sc, start_sector, &nblocks, &src); | |
1282 | 1282 | |||
1283 | if (error == 0) { | 1283 | if (error == 0) { | |
1284 | /* Do we have to erase it */ | 1284 | /* Do we have to erase it */ | |
1285 | if (! sc->sc_erased) { | 1285 | if (! sc->sc_erased) { | |
1286 | 1286 | |||
1287 | error = SectorErase(sc,src); | 1287 | error = SectorErase(sc,src); | |
1288 | if (error) | 1288 | if (error) | |
1289 | goto Out; | 1289 | goto Out; | |
1290 | sc->sc_erased = TRUE; | 1290 | sc->sc_erased = TRUE; | |
1291 | } | 1291 | } | |
1292 | SizeWritten = eflash_write_sector(sc, buffer, nblocks << DEV_BSHIFT, src, TRUE); | 1292 | SizeWritten = eflash_write_sector(sc, buffer, nblocks << DEV_BSHIFT, src, TRUE); | |
1293 | SizeWritten >>= DEV_BSHIFT; | 1293 | SizeWritten >>= DEV_BSHIFT; | |
1294 | } | 1294 | } | |
1295 | 1295 | |||
1296 | Out: | 1296 | Out: | |
1297 | if (pSizeWritten) | 1297 | if (pSizeWritten) | |
1298 | *pSizeWritten = SizeWritten; | 1298 | *pSizeWritten = SizeWritten; | |
1299 | return error; | 1299 | return error; | |
1300 | } | 1300 | } | |
1301 | 1301 | |||
1302 | /* Rest of code lifted with mods from the dev\ata\wd.c driver | 1302 | /* Rest of code lifted with mods from the dev\ata\wd.c driver | |
1303 | */ | 1303 | */ | |
1304 | 1304 | |||
1305 | /* | 1305 | /* | |
1306 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | 1306 | * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. | |
1307 | * | 1307 | * | |
1308 | * Redistribution and use in source and binary forms, with or without | 1308 | * Redistribution and use in source and binary forms, with or without | |
1309 | * modification, are permitted provided that the following conditions | 1309 | * modification, are permitted provided that the following conditions | |
1310 | * are met: | 1310 | * are met: | |
1311 | * 1. Redistributions of source code must retain the above copyright | 1311 | * 1. Redistributions of source code must retain the above copyright | |
1312 | * notice, this list of conditions and the following disclaimer. | 1312 | * notice, this list of conditions and the following disclaimer. | |
1313 | * 2. Redistributions in binary form must reproduce the above copyright | 1313 | * 2. Redistributions in binary form must reproduce the above copyright | |
1314 | * notice, this list of conditions and the following disclaimer in the | 1314 | * notice, this list of conditions and the following disclaimer in the | |
1315 | * documentation and/or other materials provided with the distribution. | 1315 | * documentation and/or other materials provided with the distribution. | |
1316 | * 3. All advertising materials mentioning features or use of this software | |||
1317 | * must display the following acknowledgement: | |||
1318 | * This product includes software developed by Manuel Bouyer. | |||
1319 | * 4. The name of the author may not be used to endorse or promote products | |||
1320 | * derived from this software without specific prior written permission. | |||
1321 | * | 1316 | * | |
1322 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 1317 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
1323 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 1318 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
1324 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 1319 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
1325 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 1320 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
1326 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 1321 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
1327 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 1322 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
1328 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 1323 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
1329 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 1324 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
1330 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 1325 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
1331 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 1326 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
1332 | */ | 1327 | */ | |
1333 | 1328 | |||
1334 | /*- | 1329 | /*- | |
1335 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | 1330 | * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. | |
1336 | * All rights reserved. | 1331 | * All rights reserved. | |
1337 | * | 1332 | * | |
1338 | * This code is derived from software contributed to The NetBSD Foundation | 1333 | * This code is derived from software contributed to The NetBSD Foundation | |
1339 | * by Charles M. Hannum and by Onno van der Linden. | 1334 | * by Charles M. Hannum and by Onno van der Linden. | |
1340 | * | 1335 | * | |
1341 | * Redistribution and use in source and binary forms, with or without | 1336 | * Redistribution and use in source and binary forms, with or without | |
1342 | * modification, are permitted provided that the following conditions | 1337 | * modification, are permitted provided that the following conditions | |
1343 | * are met: | 1338 | * are met: | |
1344 | * 1. Redistributions of source code must retain the above copyright | 1339 | * 1. Redistributions of source code must retain the above copyright | |
1345 | * notice, this list of conditions and the following disclaimer. | 1340 | * notice, this list of conditions and the following disclaimer. | |
1346 | * 2. Redistributions in binary form must reproduce the above copyright | 1341 | * 2. Redistributions in binary form must reproduce the above copyright | |
1347 | * notice, this list of conditions and the following disclaimer in the | 1342 | * notice, this list of conditions and the following disclaimer in the | |
1348 | * documentation and/or other materials provided with the distribution. | 1343 | * documentation and/or other materials provided with the distribution. | |
1349 | * 3. All advertising materials mentioning features or use of this software | 1344 | * 3. All advertising materials mentioning features or use of this software | |
1350 | * must display the following acknowledgement: | 1345 | * must display the following acknowledgement: | |
1351 | * This product includes software developed by the NetBSD | 1346 | * This product includes software developed by the NetBSD | |
1352 | * Foundation, Inc. and its contributors. | 1347 | * Foundation, Inc. and its contributors. | |
1353 | * 4. Neither the name of The NetBSD Foundation nor the names of its | 1348 | * 4. Neither the name of The NetBSD Foundation nor the names of its | |
1354 | * contributors may be used to endorse or promote products derived | 1349 | * contributors may be used to endorse or promote products derived | |
1355 | * from this software without specific prior written permission. | 1350 | * from this software without specific prior written permission. | |
1356 | * | 1351 | * | |
1357 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 1352 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
1358 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 1353 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
1359 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 1354 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
1360 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 1355 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
1361 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 1356 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
1362 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 1357 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
1363 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 1358 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
1364 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 1359 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
1365 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 1360 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
1366 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 1361 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
1367 | * POSSIBILITY OF SUCH DAMAGE. | 1362 | * POSSIBILITY OF SUCH DAMAGE. | |
1368 | */ | 1363 | */ | |
1369 | 1364 | |||
1370 | static const char ST506[] = "ST506"; | 1365 | static const char ST506[] = "ST506"; | |
1371 | 1366 | |||
1372 | #define EFLASHIORETRIES_SINGLE 4 /* number of retries before single-sector */ | 1367 | #define EFLASHIORETRIES_SINGLE 4 /* number of retries before single-sector */ | |
1373 | #define EFLASHIORETRIES 5 /* number of retries before giving up */ | 1368 | #define EFLASHIORETRIES 5 /* number of retries before giving up */ | |
1374 | #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ | 1369 | #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ | |
1375 | 1370 | |||
1376 | #define EFLASHUNIT(dev) DISKUNIT(dev) | 1371 | #define EFLASHUNIT(dev) DISKUNIT(dev) | |
1377 | #define EFLASHPART(dev) DISKPART(dev) | 1372 | #define EFLASHPART(dev) DISKPART(dev) | |
1378 | #define EFLASHMINOR(unit, part) DISKMINOR(unit, part) | 1373 | #define EFLASHMINOR(unit, part) DISKMINOR(unit, part) | |
1379 | #define MAKEEFLASHDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) | 1374 | #define MAKEEFLASHDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) | |
1380 | 1375 | |||
1381 | #define EFLASHLABELDEV(dev) (MAKEEFLASHDEV(major(dev), EFLASHUNIT(dev), RAW_PART)) | 1376 | #define EFLASHLABELDEV(dev) (MAKEEFLASHDEV(major(dev), EFLASHUNIT(dev), RAW_PART)) | |
1382 | 1377 | |||
1383 | void eflashperror(const struct eflash_softc *); | 1378 | void eflashperror(const struct eflash_softc *); | |
1384 | 1379 | |||
1385 | extern struct cfdriver eflash_cd; | 1380 | extern struct cfdriver eflash_cd; | |
1386 | 1381 | |||
1387 | dev_type_open(eflashopen); | 1382 | dev_type_open(eflashopen); | |
1388 | dev_type_close(eflashclose); | 1383 | dev_type_close(eflashclose); | |
1389 | dev_type_read(eflashread); | 1384 | dev_type_read(eflashread); | |
1390 | dev_type_write(eflashwrite); | 1385 | dev_type_write(eflashwrite); | |
1391 | dev_type_ioctl(eflashioctl); | 1386 | dev_type_ioctl(eflashioctl); | |
1392 | dev_type_strategy(eflashstrategy); | 1387 | dev_type_strategy(eflashstrategy); | |
1393 | dev_type_dump(eflashdump); | 1388 | dev_type_dump(eflashdump); | |
1394 | dev_type_size(eflashsize); | 1389 | dev_type_size(eflashsize); | |
1395 | 1390 | |||
1396 | const struct bdevsw eflash_bdevsw = { | 1391 | const struct bdevsw eflash_bdevsw = { | |
1397 | .d_open = eflashopen, | 1392 | .d_open = eflashopen, | |
1398 | .d_close = eflashclose, | 1393 | .d_close = eflashclose, | |
1399 | .d_strategy = eflashstrategy, | 1394 | .d_strategy = eflashstrategy, | |
1400 | .d_ioctl = eflashioctl, | 1395 | .d_ioctl = eflashioctl, | |
1401 | .d_dump = eflashdump, | 1396 | .d_dump = eflashdump, | |
1402 | .d_psize = eflashsize, | 1397 | .d_psize = eflashsize, | |
1403 | .d_discard = nodiscard, | 1398 | .d_discard = nodiscard, | |
1404 | .d_flag = D_DISK | 1399 | .d_flag = D_DISK | |
1405 | }; | 1400 | }; | |
1406 | 1401 | |||
1407 | const struct cdevsw eflash_cdevsw = { | 1402 | const struct cdevsw eflash_cdevsw = { | |
1408 | .d_open = eflashopen, | 1403 | .d_open = eflashopen, | |
1409 | .d_close = eflashclose, | 1404 | .d_close = eflashclose, | |
1410 | .d_read = eflashread, | 1405 | .d_read = eflashread, | |
1411 | .d_write = eflashwrite, | 1406 | .d_write = eflashwrite, | |
1412 | .d_ioctl = eflashioctl, | 1407 | .d_ioctl = eflashioctl, | |
1413 | .d_stop = nostop, | 1408 | .d_stop = nostop, | |
1414 | .d_tty = notty, | 1409 | .d_tty = notty, | |
1415 | .d_poll = nopoll, | 1410 | .d_poll = nopoll, | |
1416 | .d_mmap = nommap, | 1411 | .d_mmap = nommap, | |
1417 | .d_kqfilter = nokqfilter, | 1412 | .d_kqfilter = nokqfilter, | |
1418 | .d_discard = nodiscard, | 1413 | .d_discard = nodiscard, | |
1419 | .d_flag = D_DISK | 1414 | .d_flag = D_DISK | |
1420 | }; | 1415 | }; | |
1421 | 1416 | |||
1422 | void eflashgetdefaultlabel(struct eflash_softc *, struct disklabel *); | 1417 | void eflashgetdefaultlabel(struct eflash_softc *, struct disklabel *); | |
1423 | void eflashgetdisklabel(struct eflash_softc *); | 1418 | void eflashgetdisklabel(struct eflash_softc *); | |
1424 | void eflashstart(void *); | 1419 | void eflashstart(void *); | |
1425 | void __eflashstart(struct eflash_softc *, struct buf *); | 1420 | void __eflashstart(struct eflash_softc *, struct buf *); | |
1426 | void eflashrestart(void *); | 1421 | void eflashrestart(void *); | |
1427 | void eflashattach(struct eflash_softc *); | 1422 | void eflashattach(struct eflash_softc *); | |
1428 | int eflashdetach(device_t, int); | 1423 | int eflashdetach(device_t, int); | |
1429 | int eflashactivate(device_t, enum devact); | 1424 | int eflashactivate(device_t, enum devact); | |
1430 | 1425 | |||
1431 | void eflashdone(struct eflash_softc *); | 1426 | void eflashdone(struct eflash_softc *); | |
1432 | static void eflash_set_geometry(struct eflash_softc *sc); | 1427 | static void eflash_set_geometry(struct eflash_softc *sc); | |
1433 | 1428 | |||
1434 | struct dkdriver eflashdkdriver = { | 1429 | struct dkdriver eflashdkdriver = { | |
1435 | .d_strategy = eflashstrategy, | 1430 | .d_strategy = eflashstrategy, | |
1436 | .d_minphys = minphys | 1431 | .d_minphys = minphys | |
1437 | }; | 1432 | }; | |
1438 | 1433 | |||
1439 | #ifdef HAS_BAD144_HANDLING | 1434 | #ifdef HAS_BAD144_HANDLING | |
1440 | static void bad144intern(struct eflash_softc *); | 1435 | static void bad144intern(struct eflash_softc *); | |
1441 | #endif | 1436 | #endif | |
1442 | 1437 | |||
1443 | static void eflash_wedges(void *arg); | 1438 | static void eflash_wedges(void *arg); | |
1444 | 1439 | |||
1445 | void | 1440 | void | |
1446 | eflashattach(struct eflash_softc *sc) | 1441 | eflashattach(struct eflash_softc *sc) | |
1447 | { | 1442 | { | |
1448 | device_t self = sc->sc_dev; | 1443 | device_t self = sc->sc_dev; | |
1449 | char pbuf[9]; | 1444 | char pbuf[9]; | |
1450 | DEBUG_PRINT(("%s: eflashattach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE); | 1445 | DEBUG_PRINT(("%s: eflashattach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE); | |
1451 | 1446 | |||
1452 | callout_init(&sc->sc_restart_ch, 0); | 1447 | callout_init(&sc->sc_restart_ch, 0); | |
1453 | bufq_alloc(&sc->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); | 1448 | bufq_alloc(&sc->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); | |
1454 | 1449 | |||
1455 | sc->openings = 1; /* wazziz?*/ | 1450 | sc->openings = 1; /* wazziz?*/ | |
1456 | 1451 | |||
1457 | aprint_naive("\n"); | 1452 | aprint_naive("\n"); | |
1458 | 1453 | |||
1459 | /* setup all required fields so that if the attach fails we are ok */ | 1454 | /* setup all required fields so that if the attach fails we are ok */ | |
1460 | sc->sc_dk.dk_driver = &eflashdkdriver; | 1455 | sc->sc_dk.dk_driver = &eflashdkdriver; | |
1461 | sc->sc_dk.dk_name = device_xname(sc->sc_dev); | 1456 | sc->sc_dk.dk_name = device_xname(sc->sc_dev); | |
1462 | 1457 | |||
1463 | format_bytes(pbuf, sizeof(pbuf), sc->sc_capacity * DEV_BSIZE); | 1458 | format_bytes(pbuf, sizeof(pbuf), sc->sc_capacity * DEV_BSIZE); | |
1464 | aprint_normal("%s: %s, %d cyl, %d head, %d sec, %d bytes/sect x %llu sectors\n", | 1459 | aprint_normal("%s: %s, %d cyl, %d head, %d sec, %d bytes/sect x %llu sectors\n", | |
1465 | device_xname(self), pbuf, 1, 1, sc->sc_capacity, | 1460 | device_xname(self), pbuf, 1, 1, sc->sc_capacity, | |
1466 | DEV_BSIZE, (unsigned long long)sc->sc_capacity); | 1461 | DEV_BSIZE, (unsigned long long)sc->sc_capacity); | |
1467 | 1462 | |||
1468 | eflash_set_geometry(sc); | 1463 | eflash_set_geometry(sc); | |
1469 | 1464 | |||
1470 | /* | 1465 | /* | |
1471 | * Attach the disk structure. We fill in dk_info later. | 1466 | * Attach the disk structure. We fill in dk_info later. | |
1472 | */ | 1467 | */ | |
1473 | disk_attach(&sc->sc_dk); | 1468 | disk_attach(&sc->sc_dk); | |
1474 | 1469 | |||
1475 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | 1470 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | |
1476 | RND_TYPE_DISK, RND_FLAG_DEFAULT); | 1471 | RND_TYPE_DISK, RND_FLAG_DEFAULT); | |
1477 | 1472 | |||
1478 | } | 1473 | } | |
1479 | 1474 | |||
1480 | int | 1475 | int | |
1481 | eflashactivate(device_t self, enum devact act) | 1476 | eflashactivate(device_t self, enum devact act) | |
1482 | { | 1477 | { | |
1483 | int rv = 0; | 1478 | int rv = 0; | |
1484 | 1479 | |||
1485 | DEBUG_PRINT(("eflashactivate %x\n", act), DEBUG_FUNCS | DEBUG_PROBE); | 1480 | DEBUG_PRINT(("eflashactivate %x\n", act), DEBUG_FUNCS | DEBUG_PROBE); | |
1486 | 1481 | |||
1487 | switch (act) { | 1482 | switch (act) { | |
1488 | case DVACT_DEACTIVATE: | 1483 | case DVACT_DEACTIVATE: | |
1489 | /* | 1484 | /* | |
1490 | * Nothing to do; we key off the device's DVF_ACTIVATE. | 1485 | * Nothing to do; we key off the device's DVF_ACTIVATE. | |
1491 | */ | 1486 | */ | |
1492 | break; | 1487 | break; | |
1493 | default: | 1488 | default: | |
1494 | rv = EOPNOTSUPP; | 1489 | rv = EOPNOTSUPP; | |
1495 | break; | 1490 | break; | |
1496 | } | 1491 | } | |
1497 | return (rv); | 1492 | return (rv); | |
1498 | } | 1493 | } | |
1499 | 1494 | |||
1500 | int | 1495 | int | |
1501 | eflashdetach(device_t self, int flags) | 1496 | eflashdetach(device_t self, int flags) | |
1502 | { | 1497 | { | |
1503 | struct eflash_softc *sc = device_private(self); | 1498 | struct eflash_softc *sc = device_private(self); | |
1504 | int s, bmaj, cmaj, i, mn; | 1499 | int s, bmaj, cmaj, i, mn; | |
1505 | 1500 | |||
1506 | DEBUG_PRINT(("%s: eflashdetach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE); | 1501 | DEBUG_PRINT(("%s: eflashdetach\n", device_xname(sc->sc_dev)), DEBUG_FUNCS | DEBUG_PROBE); | |
1507 | 1502 | |||
1508 | /* locate the major number */ | 1503 | /* locate the major number */ | |
1509 | bmaj = bdevsw_lookup_major(&eflash_bdevsw); | 1504 | bmaj = bdevsw_lookup_major(&eflash_bdevsw); | |
1510 | cmaj = cdevsw_lookup_major(&eflash_cdevsw); | 1505 | cmaj = cdevsw_lookup_major(&eflash_cdevsw); | |
1511 | 1506 | |||
1512 | /* Nuke the vnodes for any open instances. */ | 1507 | /* Nuke the vnodes for any open instances. */ | |
1513 | for (i = 0; i < MAXPARTITIONS; i++) { | 1508 | for (i = 0; i < MAXPARTITIONS; i++) { | |
1514 | mn = EFLASHMINOR(device_unit(self), i); | 1509 | mn = EFLASHMINOR(device_unit(self), i); | |
1515 | vdevgone(bmaj, mn, mn, VBLK); | 1510 | vdevgone(bmaj, mn, mn, VBLK); | |
1516 | vdevgone(cmaj, mn, mn, VCHR); | 1511 | vdevgone(cmaj, mn, mn, VCHR); | |
1517 | } | 1512 | } | |
1518 | 1513 | |||
1519 | /* Delete all of our wedges. */ | 1514 | /* Delete all of our wedges. */ | |
1520 | dkwedge_delall(&sc->sc_dk); | 1515 | dkwedge_delall(&sc->sc_dk); | |
1521 | 1516 | |||
1522 | s = splbio(); | 1517 | s = splbio(); | |
1523 | 1518 | |||
1524 | /* Kill off any queued buffers. */ | 1519 | /* Kill off any queued buffers. */ | |
1525 | bufq_drain(sc->sc_q); | 1520 | bufq_drain(sc->sc_q); | |
1526 | 1521 | |||
1527 | /*sc->atabus->ata_killpending(sc->drvp);*/ | 1522 | /*sc->atabus->ata_killpending(sc->drvp);*/ | |
1528 | 1523 | |||
1529 | splx(s); | 1524 | splx(s); | |
1530 | bufq_free(sc->sc_q); | 1525 | bufq_free(sc->sc_q); | |
1531 | 1526 | |||
1532 | /* Detach disk. */ | 1527 | /* Detach disk. */ | |
1533 | disk_detach(&sc->sc_dk); | 1528 | disk_detach(&sc->sc_dk); | |
1534 | 1529 | |||
1535 | /* Unhook the entropy source. */ | 1530 | /* Unhook the entropy source. */ | |
1536 | rnd_detach_source(&sc->rnd_source); | 1531 | rnd_detach_source(&sc->rnd_source); | |
1537 | 1532 | |||
1538 | /*sc->drvp->drive_flags = 0; -- no drive any more here */ | 1533 | /*sc->drvp->drive_flags = 0; -- no drive any more here */ | |
1539 | 1534 | |||
1540 | return (0); | 1535 | return (0); | |
1541 | } | 1536 | } | |
1542 | 1537 | |||
1543 | extern int dkwedge_autodiscover; | 1538 | extern int dkwedge_autodiscover; | |
1544 | 1539 | |||
1545 | /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing. | 1540 | /* Aux temp thread to avoid deadlock when doing the partitio.. ahem wedges thing. | |
1546 | */ | 1541 | */ | |
1547 | static void | 1542 | static void | |
1548 | eflash_wedges(void *arg) | 1543 | eflash_wedges(void *arg) | |
1549 | { | 1544 | { | |
1550 | struct eflash_softc *sc = (struct eflash_softc*)arg; | 1545 | struct eflash_softc *sc = (struct eflash_softc*)arg; | |
1551 | 1546 | |||
1552 | DBGME(DEBUG_STATUS,printf("%s: wedges started for %p\n", sc->sc_dk.dk_name, sc)); | 1547 | DBGME(DEBUG_STATUS,printf("%s: wedges started for %p\n", sc->sc_dk.dk_name, sc)); | |
1553 | 1548 | |||
1554 | /* Discover wedges on this disk. */ | 1549 | /* Discover wedges on this disk. */ | |
1555 | dkwedge_autodiscover = 1; | 1550 | dkwedge_autodiscover = 1; | |
1556 | dkwedge_discover(&sc->sc_dk); | 1551 | dkwedge_discover(&sc->sc_dk); | |
1557 | 1552 | |||
1558 | config_pending_decr(sc->sc_dev); | 1553 | config_pending_decr(sc->sc_dev); | |
1559 | 1554 | |||
1560 | DBGME(DEBUG_STATUS,printf("%s: wedges thread done for %p\n", device_xname(sc->sc_dev), sc)); | 1555 | DBGME(DEBUG_STATUS,printf("%s: wedges thread done for %p\n", device_xname(sc->sc_dev), sc)); | |
1561 | kthread_exit(0); | 1556 | kthread_exit(0); | |
1562 | } | 1557 | } | |
1563 | 1558 | |||
1564 | static void | 1559 | static void | |
1565 | eflash_thread(void *arg) | 1560 | eflash_thread(void *arg) | |
1566 | { | 1561 | { | |
1567 | struct eflash_softc *sc = (struct eflash_softc*)arg; | 1562 | struct eflash_softc *sc = (struct eflash_softc*)arg; | |
1568 | struct buf *bp; | 1563 | struct buf *bp; | |
1569 | vaddr_t addr; | 1564 | vaddr_t addr; | |
1570 | int s, error; | 1565 | int s, error; | |
1571 | 1566 | |||
1572 | DBGME(DEBUG_STATUS,printf("%s: thread started for %p\n", device_xname(sc->sc_dev), sc)); | 1567 | DBGME(DEBUG_STATUS,printf("%s: thread started for %p\n", device_xname(sc->sc_dev), sc)); | |
1573 | 1568 | |||
1574 | s = splbio(); | 1569 | s = splbio(); | |
1575 | eflashattach(sc); | 1570 | eflashattach(sc); | |
1576 | splx(s); | 1571 | splx(s); | |
1577 | 1572 | |||
1578 | /* Allocate a VM window large enough to map the largest sector | 1573 | /* Allocate a VM window large enough to map the largest sector | |
1579 | * BUGBUG We could risk it and allocate/free on open/close? | 1574 | * BUGBUG We could risk it and allocate/free on open/close? | |
1580 | */ | 1575 | */ | |
1581 | addr = uvm_km_alloc(kernel_map, sc->sc_max_secsize, 0, UVM_KMF_VAONLY); | 1576 | addr = uvm_km_alloc(kernel_map, sc->sc_max_secsize, 0, UVM_KMF_VAONLY); | |
1582 | if (addr == 0) | 1577 | if (addr == 0) | |
1583 | panic("eflash_thread: kernel map full (%lx)", (long unsigned)sc->sc_max_secsize); | 1578 | panic("eflash_thread: kernel map full (%lx)", (long unsigned)sc->sc_max_secsize); | |
1584 | sc->sc_sector = (/*volatile*/ uint8_t *) addr; | 1579 | sc->sc_sector = (/*volatile*/ uint8_t *) addr; | |
1585 | sc->sc_sector_size = 0; | 1580 | sc->sc_sector_size = 0; | |
1586 | sc->sc_sector_offset = NOSECTOR; | 1581 | sc->sc_sector_offset = NOSECTOR; | |
1587 | 1582 | |||
1588 | error = kthread_create(PRI_NONE, 0, NULL, | 1583 | error = kthread_create(PRI_NONE, 0, NULL, | |
1589 | eflash_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev)); | 1584 | eflash_wedges, sc, NULL, "%s.wedges", device_xname(sc->sc_dev)); | |
1590 | if (error) { | 1585 | if (error) { | |
1591 | aprint_error_dev(sc->sc_dev, "wedges: unable to create kernel " | 1586 | aprint_error_dev(sc->sc_dev, "wedges: unable to create kernel " | |
1592 | "thread: error %d\n", error); | 1587 | "thread: error %d\n", error); | |
1593 | /* XXX: why continue? */ | 1588 | /* XXX: why continue? */ | |
1594 | } | 1589 | } | |
1595 | 1590 | |||
1596 | 1591 | |||
1597 | DBGME(DEBUG_STATUS,printf("%s: thread service active for %p\n", device_xname(sc->sc_dev), sc)); | 1592 | DBGME(DEBUG_STATUS,printf("%s: thread service active for %p\n", device_xname(sc->sc_dev), sc)); | |
1598 | 1593 | |||
1599 | s = splbio(); | 1594 | s = splbio(); | |
1600 | for (;;) { | 1595 | for (;;) { | |
1601 | /* Get next I/O request, wait if necessary | 1596 | /* Get next I/O request, wait if necessary | |
1602 | */ | 1597 | */ | |
1603 | if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && | 1598 | if ((sc->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && | |
1604 | (sc->active_xfer == NULL)) { | 1599 | (sc->active_xfer == NULL)) { | |
1605 | sc->ch_flags &= ~ATACH_TH_RUN; | 1600 | sc->ch_flags &= ~ATACH_TH_RUN; | |
1606 | (void) tsleep(&sc->ch_thread, PRIBIO, "eflashth", 0); | 1601 | (void) tsleep(&sc->ch_thread, PRIBIO, "eflashth", 0); | |
1607 | sc->ch_flags |= ATACH_TH_RUN; | 1602 | sc->ch_flags |= ATACH_TH_RUN; | |
1608 | } | 1603 | } | |
1609 | if (sc->ch_flags & ATACH_SHUTDOWN) { | 1604 | if (sc->ch_flags & ATACH_SHUTDOWN) { | |
1610 | break; | 1605 | break; | |
1611 | } | 1606 | } | |
1612 | bp = sc->active_xfer; | 1607 | bp = sc->active_xfer; | |
1613 | sc->active_xfer = NULL; | 1608 | sc->active_xfer = NULL; | |
1614 | if (bp != NULL) { | 1609 | if (bp != NULL) { | |
1615 | 1610 | |||
1616 | size_t sz = DEV_BSIZE, bnow; | 1611 | size_t sz = DEV_BSIZE, bnow; | |
1617 | 1612 | |||
1618 | DBGME(DEBUG_XFERS,printf("%s: task %p %x %p %qx %d (%zd)\n", device_xname(sc->sc_dev), bp, | 1613 | DBGME(DEBUG_XFERS,printf("%s: task %p %x %p %qx %d (%zd)\n", device_xname(sc->sc_dev), bp, | |
1619 | sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno, | 1614 | sc->sc_bio.flags, sc->sc_bio.databuf, sc->sc_bio.blkno, | |
1620 | sc->sc_bio.nbytes, sc->sc_bio.nblks)); | 1615 | sc->sc_bio.nbytes, sc->sc_bio.nblks)); | |
1621 | 1616 | |||
1622 | sc->sc_bio.error = 0; | 1617 | sc->sc_bio.error = 0; | |
1623 | for (; sc->sc_bio.nblks > 0;) { | 1618 | for (; sc->sc_bio.nblks > 0;) { | |
1624 | 1619 | |||
1625 | bnow = sc->sc_bio.nblks; | 1620 | bnow = sc->sc_bio.nblks; | |
1626 | if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1; | 1621 | if (sc->sc_bio.flags & ATA_SINGLE) bnow = 1; | |
1627 | 1622 | |||
1628 | if (sc->sc_bio.flags & ATA_READ) { | 1623 | if (sc->sc_bio.flags & ATA_READ) { | |
1629 | sc->sc_bio.error = | 1624 | sc->sc_bio.error = | |
1630 | eflash_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz); | 1625 | eflash_read_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz); | |
1631 | } else { | 1626 | } else { | |
1632 | sc->sc_bio.error = | 1627 | sc->sc_bio.error = | |
1633 | eflash_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz); | 1628 | eflash_write_at(sc, sc->sc_bio.blkno, sc->sc_bio.databuf, bnow, &sz); | |
1634 | } | 1629 | } | |
1635 | 1630 | |||
1636 | if (sc->sc_bio.error) | 1631 | if (sc->sc_bio.error) | |
1637 | break; | 1632 | break; | |
1638 | 1633 | |||
1639 | sc->sc_bio.blkno += sz; /* in blocks */ | 1634 | sc->sc_bio.blkno += sz; /* in blocks */ | |
1640 | sc->sc_bio.nblks -= sz; | 1635 | sc->sc_bio.nblks -= sz; | |
1641 | sc->sc_bio.blkdone += sz; | 1636 | sc->sc_bio.blkdone += sz; | |
1642 | sz = sz << DEV_BSHIFT; /* in bytes */ | 1637 | sz = sz << DEV_BSHIFT; /* in bytes */ | |
1643 | sc->sc_bio.databuf += sz; | 1638 | sc->sc_bio.databuf += sz; | |
1644 | sc->sc_bio.nbytes -= sz; | 1639 | sc->sc_bio.nbytes -= sz; | |
1645 | } | 1640 | } | |
1646 | 1641 | |||
1647 | eflashdone(sc); | 1642 | eflashdone(sc); | |
1648 | } | 1643 | } | |
1649 | } | 1644 | } | |
1650 | 1645 | |||
1651 | splx(s); | 1646 | splx(s); | |
1652 | sc->ch_thread = NULL; | 1647 | sc->ch_thread = NULL; | |
1653 | wakeup(&sc->ch_flags); | 1648 | wakeup(&sc->ch_flags); | |
1654 | 1649 | |||
1655 | DBGME(DEBUG_STATUS,printf("%s: thread service terminated for %p\n", device_xname(sc->sc_dev), sc)); | 1650 | DBGME(DEBUG_STATUS,printf("%s: thread service terminated for %p\n", device_xname(sc->sc_dev), sc)); | |
1656 | 1651 | |||
1657 | kthread_exit(0); | 1652 | kthread_exit(0); | |
1658 | } | 1653 | } | |
1659 | 1654 | |||
1660 | 1655 | |||
1661 | /* | 1656 | /* | |
1662 | * Read/write routine for a buffer. Validates the arguments and schedules the | 1657 | * Read/write routine for a buffer. Validates the arguments and schedules the | |
1663 | * transfer. Does not wait for the transfer to complete. | 1658 | * transfer. Does not wait for the transfer to complete. | |
1664 | */ | 1659 | */ | |
1665 | void | 1660 | void | |
1666 | eflashstrategy(struct buf *bp) | 1661 | eflashstrategy(struct buf *bp) | |
1667 | { | 1662 | { | |
1668 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(bp->b_dev)); | 1663 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(bp->b_dev)); | |
1669 | struct disklabel *lp = sc->sc_dk.dk_label; | 1664 | struct disklabel *lp = sc->sc_dk.dk_label; | |
1670 | daddr_t blkno; | 1665 | daddr_t blkno; | |
1671 | int s; | 1666 | int s; | |
1672 | 1667 | |||
1673 | DEBUG_PRINT(("%s: eflashstrategy %lld\n", device_xname(sc->sc_dev), bp->b_blkno), | 1668 | DEBUG_PRINT(("%s: eflashstrategy %lld\n", device_xname(sc->sc_dev), bp->b_blkno), | |
1674 | DEBUG_XFERS); | 1669 | DEBUG_XFERS); | |
1675 | 1670 | |||
1676 | /* Valid request? */ | 1671 | /* Valid request? */ | |
1677 | if (bp->b_blkno < 0 || | 1672 | if (bp->b_blkno < 0 || | |
1678 | (bp->b_bcount % lp->d_secsize) != 0 || | 1673 | (bp->b_bcount % lp->d_secsize) != 0 || | |
1679 | (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { | 1674 | (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { | |
1680 | bp->b_error = EINVAL; | 1675 | bp->b_error = EINVAL; | |
1681 | goto done; | 1676 | goto done; | |
1682 | } | 1677 | } | |
1683 | 1678 | |||
1684 | /* If device invalidated (e.g. media change, door open), error. */ | 1679 | /* If device invalidated (e.g. media change, door open), error. */ | |
1685 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | 1680 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | |
1686 | bp->b_error = EIO; | 1681 | bp->b_error = EIO; | |
1687 | goto done; | 1682 | goto done; | |
1688 | } | 1683 | } | |
1689 | 1684 | |||
1690 | /* If it's a null transfer, return immediately. */ | 1685 | /* If it's a null transfer, return immediately. */ | |
1691 | if (bp->b_bcount == 0) | 1686 | if (bp->b_bcount == 0) | |
1692 | goto done; | 1687 | goto done; | |
1693 | 1688 | |||
1694 | /* | 1689 | /* | |
1695 | * Do bounds checking, adjust transfer. if error, process. | 1690 | * Do bounds checking, adjust transfer. if error, process. | |
1696 | * If end of partition, just return. | 1691 | * If end of partition, just return. | |
1697 | */ | 1692 | */ | |
1698 | if (EFLASHPART(bp->b_dev) == RAW_PART) { | 1693 | if (EFLASHPART(bp->b_dev) == RAW_PART) { | |
1699 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, | 1694 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, | |
1700 | sc->sc_capacity) <= 0) | 1695 | sc->sc_capacity) <= 0) | |
1701 | goto done; | 1696 | goto done; | |
1702 | } else { | 1697 | } else { | |
1703 | if (bounds_check_with_label(&sc->sc_dk, bp, | 1698 | if (bounds_check_with_label(&sc->sc_dk, bp, | |
1704 | (sc->sc_flags & (EFLASHF_WLABEL|EFLASHF_LABELLING)) != 0) <= 0) | 1699 | (sc->sc_flags & (EFLASHF_WLABEL|EFLASHF_LABELLING)) != 0) <= 0) | |
1705 | goto done; | 1700 | goto done; | |
1706 | } | 1701 | } | |
1707 | 1702 | |||
1708 | /* | 1703 | /* | |
1709 | * Now convert the block number to absolute and put it in | 1704 | * Now convert the block number to absolute and put it in | |
1710 | * terms of the device's logical block size. | 1705 | * terms of the device's logical block size. | |
1711 | */ | 1706 | */ | |
1712 | if (lp->d_secsize >= DEV_BSIZE) | 1707 | if (lp->d_secsize >= DEV_BSIZE) | |
1713 | blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); | 1708 | blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); | |
1714 | else | 1709 | else | |
1715 | blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); | 1710 | blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); | |
1716 | 1711 | |||
1717 | if (EFLASHPART(bp->b_dev) != RAW_PART) | 1712 | if (EFLASHPART(bp->b_dev) != RAW_PART) | |
1718 | blkno += lp->d_partitions[EFLASHPART(bp->b_dev)].p_offset; | 1713 | blkno += lp->d_partitions[EFLASHPART(bp->b_dev)].p_offset; | |
1719 | 1714 | |||
1720 | bp->b_rawblkno = blkno; | 1715 | bp->b_rawblkno = blkno; | |
1721 | 1716 | |||
1722 | /* Queue transfer on drive, activate drive and controller if idle. */ | 1717 | /* Queue transfer on drive, activate drive and controller if idle. */ | |
1723 | s = splbio(); | 1718 | s = splbio(); | |
1724 | bufq_put(sc->sc_q, bp); | 1719 | bufq_put(sc->sc_q, bp); | |
1725 | eflashstart(sc); | 1720 | eflashstart(sc); | |
1726 | splx(s); | 1721 | splx(s); | |
1727 | return; | 1722 | return; | |
1728 | done: | 1723 | done: | |
1729 | /* Toss transfer; we're done early. */ | 1724 | /* Toss transfer; we're done early. */ | |
1730 | bp->b_resid = bp->b_bcount; | 1725 | bp->b_resid = bp->b_bcount; | |
1731 | biodone(bp); | 1726 | biodone(bp); | |
1732 | } | 1727 | } | |
1733 | 1728 | |||
1734 | /* | 1729 | /* | |
1735 | * Queue a drive for I/O. | 1730 | * Queue a drive for I/O. | |
1736 | */ | 1731 | */ | |
1737 | void | 1732 | void | |
1738 | eflashstart(void *arg) | 1733 | eflashstart(void *arg) | |
1739 | { | 1734 | { | |
1740 | struct eflash_softc *sc = arg; | 1735 | struct eflash_softc *sc = arg; | |
1741 | struct buf *bp = NULL; | 1736 | struct buf *bp = NULL; | |
1742 | 1737 | |||
1743 | DEBUG_PRINT(("%s: eflashstart\n", device_xname(sc->sc_dev)), | 1738 | DEBUG_PRINT(("%s: eflashstart\n", device_xname(sc->sc_dev)), | |
1744 | DEBUG_XFERS); | 1739 | DEBUG_XFERS); | |
1745 | while (sc->openings > 0) { | 1740 | while (sc->openings > 0) { | |
1746 | 1741 | |||
1747 | /* Is there a buf for us ? */ | 1742 | /* Is there a buf for us ? */ | |
1748 | if ((bp = bufq_get(sc->sc_q)) == NULL) | 1743 | if ((bp = bufq_get(sc->sc_q)) == NULL) | |
1749 | return; | 1744 | return; | |
1750 | 1745 | |||
1751 | /* | 1746 | /* | |
1752 | * Make the command. First lock the device | 1747 | * Make the command. First lock the device | |
1753 | */ | 1748 | */ | |
1754 | sc->openings--; | 1749 | sc->openings--; | |
1755 | 1750 | |||
1756 | sc->retries = 0; | 1751 | sc->retries = 0; | |
1757 | __eflashstart(sc, bp); | 1752 | __eflashstart(sc, bp); | |
1758 | } | 1753 | } | |
1759 | } | 1754 | } | |
1760 | 1755 | |||
1761 | void | 1756 | void | |
1762 | __eflashstart(struct eflash_softc *sc, struct buf *bp) | 1757 | __eflashstart(struct eflash_softc *sc, struct buf *bp) | |
1763 | { | 1758 | { | |
1764 | DEBUG_PRINT(("%s: __eflashstart %p\n", device_xname(sc->sc_dev), bp), | 1759 | DEBUG_PRINT(("%s: __eflashstart %p\n", device_xname(sc->sc_dev), bp), | |
1765 | DEBUG_XFERS); | 1760 | DEBUG_XFERS); | |
1766 | 1761 | |||
1767 | sc->sc_bp = bp; | 1762 | sc->sc_bp = bp; | |
1768 | /* | 1763 | /* | |
1769 | * If we're retrying, retry in single-sector mode. This will give us | 1764 | * If we're retrying, retry in single-sector mode. This will give us | |
1770 | * the sector number of the problem, and will eventually allow the | 1765 | * the sector number of the problem, and will eventually allow the | |
1771 | * transfer to succeed. | 1766 | * transfer to succeed. | |
1772 | */ | 1767 | */ | |
1773 | if (sc->retries >= EFLASHIORETRIES_SINGLE) | 1768 | if (sc->retries >= EFLASHIORETRIES_SINGLE) | |
1774 | sc->sc_bio.flags = ATA_SINGLE; | 1769 | sc->sc_bio.flags = ATA_SINGLE; | |
1775 | else | 1770 | else | |
1776 | sc->sc_bio.flags = 0; | 1771 | sc->sc_bio.flags = 0; | |
1777 | if (bp->b_flags & B_READ) | 1772 | if (bp->b_flags & B_READ) | |
1778 | sc->sc_bio.flags |= ATA_READ; | 1773 | sc->sc_bio.flags |= ATA_READ; | |
1779 | sc->sc_bio.blkno = bp->b_rawblkno; | 1774 | sc->sc_bio.blkno = bp->b_rawblkno; | |
1780 | sc->sc_bio.blkdone = 0; | 1775 | sc->sc_bio.blkdone = 0; | |
1781 | sc->sc_bio.nbytes = bp->b_bcount; | 1776 | sc->sc_bio.nbytes = bp->b_bcount; | |
1782 | sc->sc_bio.nblks = bp->b_bcount >> DEV_BSHIFT; | 1777 | sc->sc_bio.nblks = bp->b_bcount >> DEV_BSHIFT; | |
1783 | sc->sc_bio.databuf = bp->b_data; | 1778 | sc->sc_bio.databuf = bp->b_data; | |
1784 | /* Instrumentation. */ | 1779 | /* Instrumentation. */ | |
1785 | disk_busy(&sc->sc_dk); | 1780 | disk_busy(&sc->sc_dk); | |
1786 | sc->active_xfer = bp; | 1781 | sc->active_xfer = bp; | |
1787 | wakeup(&sc->ch_thread); | 1782 | wakeup(&sc->ch_thread); | |
1788 | } | 1783 | } | |
1789 | 1784 | |||
1790 | void | 1785 | void | |
1791 | eflashdone(struct eflash_softc *sc) | 1786 | eflashdone(struct eflash_softc *sc) | |
1792 | { | 1787 | { | |
1793 | struct buf *bp = sc->sc_bp; | 1788 | struct buf *bp = sc->sc_bp; | |
1794 | const char *errmsg; | 1789 | const char *errmsg; | |
1795 | int do_perror = 0; | 1790 | int do_perror = 0; | |
1796 | 1791 | |||
1797 | DEBUG_PRINT(("%s: eflashdone %p\n", device_xname(sc->sc_dev), bp), | 1792 | DEBUG_PRINT(("%s: eflashdone %p\n", device_xname(sc->sc_dev), bp), | |
1798 | DEBUG_XFERS); | 1793 | DEBUG_XFERS); | |
1799 | 1794 | |||
1800 | if (bp == NULL) | 1795 | if (bp == NULL) | |
1801 | return; | 1796 | return; | |
1802 | 1797 | |||
1803 | bp->b_resid = sc->sc_bio.nbytes; | 1798 | bp->b_resid = sc->sc_bio.nbytes; | |
1804 | switch (sc->sc_bio.error) { | 1799 | switch (sc->sc_bio.error) { | |
1805 | case ETIMEDOUT: | 1800 | case ETIMEDOUT: | |
1806 | errmsg = "device timeout"; | 1801 | errmsg = "device timeout"; | |
1807 | do_perror = 1; | 1802 | do_perror = 1; | |
1808 | goto retry; | 1803 | goto retry; | |
1809 | case EBUSY: | 1804 | case EBUSY: | |
1810 | errmsg = "device stuck"; | 1805 | errmsg = "device stuck"; | |
1811 | retry: /* Just reset and retry. Can we do more ? */ | 1806 | retry: /* Just reset and retry. Can we do more ? */ | |
1812 | /*eflash_reset(sc);*/ | 1807 | /*eflash_reset(sc);*/ | |
1813 | diskerr(bp, "flash", errmsg, LOG_PRINTF, | 1808 | diskerr(bp, "flash", errmsg, LOG_PRINTF, | |
1814 | sc->sc_bio.blkdone, sc->sc_dk.dk_label); | 1809 | sc->sc_bio.blkdone, sc->sc_dk.dk_label); | |
1815 | if (sc->retries < EFLASHIORETRIES) | 1810 | if (sc->retries < EFLASHIORETRIES) | |
1816 | printf(", retrying"); | 1811 | printf(", retrying"); | |
1817 | printf("\n"); | 1812 | printf("\n"); | |
1818 | if (do_perror) | 1813 | if (do_perror) | |
1819 | eflashperror(sc); | 1814 | eflashperror(sc); | |
1820 | if (sc->retries < EFLASHIORETRIES) { | 1815 | if (sc->retries < EFLASHIORETRIES) { | |
1821 | sc->retries++; | 1816 | sc->retries++; | |
1822 | callout_reset(&sc->sc_restart_ch, RECOVERYTIME, | 1817 | callout_reset(&sc->sc_restart_ch, RECOVERYTIME, | |
1823 | eflashrestart, sc); | 1818 | eflashrestart, sc); | |
1824 | return; | 1819 | return; | |
1825 | } | 1820 | } | |
1826 | 1821 | |||
1827 | bp->b_error = EIO; | 1822 | bp->b_error = EIO; | |
1828 | break; | 1823 | break; | |
1829 | case 0: | 1824 | case 0: | |
1830 | if ((sc->sc_bio.flags & ATA_CORR) || sc->retries > 0) | 1825 | if ((sc->sc_bio.flags & ATA_CORR) || sc->retries > 0) | |
1831 | printf("%s: soft error (corrected)\n", | 1826 | printf("%s: soft error (corrected)\n", | |
1832 | device_xname(sc->sc_dev)); | 1827 | device_xname(sc->sc_dev)); | |
1833 | break; | 1828 | break; | |
1834 | case ENODEV: | 1829 | case ENODEV: | |
1835 | case E2BIG: | 1830 | case E2BIG: | |
1836 | bp->b_error = EIO; | 1831 | bp->b_error = EIO; | |
1837 | break; | 1832 | break; | |
1838 | } | 1833 | } | |
1839 | disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid), | 1834 | disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid), | |
1840 | (bp->b_flags & B_READ)); | 1835 | (bp->b_flags & B_READ)); | |
1841 | rnd_add_uint32(&sc->rnd_source, bp->b_blkno); | 1836 | rnd_add_uint32(&sc->rnd_source, bp->b_blkno); | |
1842 | biodone(bp); | 1837 | biodone(bp); | |
1843 | sc->openings++; | 1838 | sc->openings++; | |
1844 | eflashstart(sc); | 1839 | eflashstart(sc); | |
1845 | } | 1840 | } | |
1846 | 1841 | |||
1847 | void | 1842 | void | |
1848 | eflashrestart(void *v) | 1843 | eflashrestart(void *v) | |
1849 | { | 1844 | { | |
1850 | struct eflash_softc *sc = v; | 1845 | struct eflash_softc *sc = v; | |
1851 | struct buf *bp = sc->sc_bp; | 1846 | struct buf *bp = sc->sc_bp; | |
1852 | int s; | 1847 | int s; | |
1853 | DEBUG_PRINT(("%s: eflashrestart\n", device_xname(sc->sc_dev)), | 1848 | DEBUG_PRINT(("%s: eflashrestart\n", device_xname(sc->sc_dev)), | |
1854 | DEBUG_XFERS); | 1849 | DEBUG_XFERS); | |
1855 | 1850 | |||
1856 | s = splbio(); | 1851 | s = splbio(); | |
1857 | __eflashstart(v, bp); | 1852 | __eflashstart(v, bp); | |
1858 | splx(s); | 1853 | splx(s); | |
1859 | } | 1854 | } | |
1860 | 1855 | |||
1861 | int | 1856 | int | |
1862 | eflashread(dev_t dev, struct uio *uio, int flags) | 1857 | eflashread(dev_t dev, struct uio *uio, int flags) | |
1863 | { | 1858 | { | |
1864 | DEBUG_PRINT(("eflashread\n"), DEBUG_XFERS); | 1859 | DEBUG_PRINT(("eflashread\n"), DEBUG_XFERS); | |
1865 | return (physio(eflashstrategy, NULL, dev, B_READ, minphys, uio)); | 1860 | return (physio(eflashstrategy, NULL, dev, B_READ, minphys, uio)); | |
1866 | } | 1861 | } | |
1867 | 1862 | |||
1868 | int | 1863 | int | |
1869 | eflashwrite(dev_t dev, struct uio *uio, int flags) | 1864 | eflashwrite(dev_t dev, struct uio *uio, int flags) | |
1870 | { | 1865 | { | |
1871 | DEBUG_PRINT(("eflashwrite\n"), DEBUG_XFERS); | 1866 | DEBUG_PRINT(("eflashwrite\n"), DEBUG_XFERS); | |
1872 | return (physio(eflashstrategy, NULL, dev, B_WRITE, minphys, uio)); | 1867 | return (physio(eflashstrategy, NULL, dev, B_WRITE, minphys, uio)); | |
1873 | } | 1868 | } | |
1874 | 1869 | |||
1875 | int | 1870 | int | |
1876 | eflashopen(dev_t dev, int flag, int fmt, struct lwp *l) | 1871 | eflashopen(dev_t dev, int flag, int fmt, struct lwp *l) | |
1877 | { | 1872 | { | |
1878 | struct eflash_softc *sc; | 1873 | struct eflash_softc *sc; | |
1879 | int part, error; | 1874 | int part, error; | |
1880 | 1875 | |||
1881 | DEBUG_PRINT(("eflashopen %" PRIx64 "\n", dev), DEBUG_FUNCS); | 1876 | DEBUG_PRINT(("eflashopen %" PRIx64 "\n", dev), DEBUG_FUNCS); | |
1882 | sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | 1877 | sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | |
1883 | if (sc == NULL) | 1878 | if (sc == NULL) | |
1884 | return (ENXIO); | 1879 | return (ENXIO); | |
1885 | 1880 | |||
1886 | if (! device_is_active(sc->sc_dev)) | 1881 | if (! device_is_active(sc->sc_dev)) | |
1887 | return (ENODEV); | 1882 | return (ENODEV); | |
1888 | 1883 | |||
1889 | part = EFLASHPART(dev); | 1884 | part = EFLASHPART(dev); | |
1890 | 1885 | |||
1891 | mutex_enter(&sc->sc_dk.dk_openlock); | 1886 | mutex_enter(&sc->sc_dk.dk_openlock); | |
1892 | 1887 | |||
1893 | /* | 1888 | /* | |
1894 | * If there are wedges, and this is not RAW_PART, then we | 1889 | * If there are wedges, and this is not RAW_PART, then we | |
1895 | * need to fail. | 1890 | * need to fail. | |
1896 | */ | 1891 | */ | |
1897 | if (sc->sc_dk.dk_nwedges != 0 && part != RAW_PART) { | 1892 | if (sc->sc_dk.dk_nwedges != 0 && part != RAW_PART) { | |
1898 | error = EBUSY; | 1893 | error = EBUSY; | |
1899 | goto bad; | 1894 | goto bad; | |
1900 | } | 1895 | } | |
1901 | 1896 | |||
1902 | if (sc->sc_dk.dk_openmask != 0) { | 1897 | if (sc->sc_dk.dk_openmask != 0) { | |
1903 | /* | 1898 | /* | |
1904 | * If any partition is open, but the disk has been invalidated, | 1899 | * If any partition is open, but the disk has been invalidated, | |
1905 | * disallow further opens. | 1900 | * disallow further opens. | |
1906 | */ | 1901 | */ | |
1907 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | 1902 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | |
1908 | error = EIO; | 1903 | error = EIO; | |
1909 | goto bad; | 1904 | goto bad; | |
1910 | } | 1905 | } | |
1911 | } else { | 1906 | } else { | |
1912 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | 1907 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) { | |
1913 | sc->sc_flags |= EFLASHF_LOADED; | 1908 | sc->sc_flags |= EFLASHF_LOADED; | |
1914 | 1909 | |||
1915 | /* Load the partition info if not already loaded. */ | 1910 | /* Load the partition info if not already loaded. */ | |
1916 | eflashgetdisklabel(sc); | 1911 | eflashgetdisklabel(sc); | |
1917 | } | 1912 | } | |
1918 | } | 1913 | } | |
1919 | 1914 | |||
1920 | /* Check that the partition exists. */ | 1915 | /* Check that the partition exists. */ | |
1921 | if (part != RAW_PART && | 1916 | if (part != RAW_PART && | |
1922 | (part >= sc->sc_dk.dk_label->d_npartitions || | 1917 | (part >= sc->sc_dk.dk_label->d_npartitions || | |
1923 | sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { | 1918 | sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { | |
1924 | error = ENXIO; | 1919 | error = ENXIO; | |
1925 | goto bad; | 1920 | goto bad; | |
1926 | } | 1921 | } | |
1927 | 1922 | |||
1928 | /* Insure only one open at a time. */ | 1923 | /* Insure only one open at a time. */ | |
1929 | switch (fmt) { | 1924 | switch (fmt) { | |
1930 | case S_IFCHR: | 1925 | case S_IFCHR: | |
1931 | sc->sc_dk.dk_copenmask |= (1 << part); | 1926 | sc->sc_dk.dk_copenmask |= (1 << part); | |
1932 | break; | 1927 | break; | |
1933 | case S_IFBLK: | 1928 | case S_IFBLK: | |
1934 | sc->sc_dk.dk_bopenmask |= (1 << part); | 1929 | sc->sc_dk.dk_bopenmask |= (1 << part); | |
1935 | break; | 1930 | break; | |
1936 | } | 1931 | } | |
1937 | sc->sc_dk.dk_openmask = | 1932 | sc->sc_dk.dk_openmask = | |
1938 | sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; | 1933 | sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; | |
1939 | 1934 | |||
1940 | mutex_exit(&sc->sc_dk.dk_openlock); | 1935 | mutex_exit(&sc->sc_dk.dk_openlock); | |
1941 | return 0; | 1936 | return 0; | |
1942 | 1937 | |||
1943 | bad: | 1938 | bad: | |
1944 | mutex_exit(&sc->sc_dk.dk_openlock); | 1939 | mutex_exit(&sc->sc_dk.dk_openlock); | |
1945 | DEBUG_PRINT(("%s: eflashopen -> %d\n", device_xname(sc->sc_dev), error), | 1940 | DEBUG_PRINT(("%s: eflashopen -> %d\n", device_xname(sc->sc_dev), error), | |
1946 | DEBUG_XFERS); | 1941 | DEBUG_XFERS); | |
1947 | return error; | 1942 | return error; | |
1948 | } | 1943 | } | |
1949 | 1944 | |||
1950 | int | 1945 | int | |
1951 | eflashclose(dev_t dev, int flag, int fmt, struct lwp *l) | 1946 | eflashclose(dev_t dev, int flag, int fmt, struct lwp *l) | |
1952 | { | 1947 | { | |
1953 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | 1948 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | |
1954 | int part = EFLASHPART(dev); | 1949 | int part = EFLASHPART(dev); | |
1955 | 1950 | |||
1956 | DEBUG_PRINT(("eflashclose %" PRIx64 "\n", dev), DEBUG_FUNCS); | 1951 | DEBUG_PRINT(("eflashclose %" PRIx64 "\n", dev), DEBUG_FUNCS); | |
1957 | 1952 | |||
1958 | mutex_enter(&sc->sc_dk.dk_openlock); | 1953 | mutex_enter(&sc->sc_dk.dk_openlock); | |
1959 | 1954 | |||
1960 | switch (fmt) { | 1955 | switch (fmt) { | |
1961 | case S_IFCHR: | 1956 | case S_IFCHR: | |
1962 | sc->sc_dk.dk_copenmask &= ~(1 << part); | 1957 | sc->sc_dk.dk_copenmask &= ~(1 << part); | |
1963 | break; | 1958 | break; | |
1964 | case S_IFBLK: | 1959 | case S_IFBLK: | |
1965 | sc->sc_dk.dk_bopenmask &= ~(1 << part); | 1960 | sc->sc_dk.dk_bopenmask &= ~(1 << part); | |
1966 | break; | 1961 | break; | |
1967 | } | 1962 | } | |
1968 | sc->sc_dk.dk_openmask = | 1963 | sc->sc_dk.dk_openmask = | |
1969 | sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; | 1964 | sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; | |
1970 | 1965 | |||
1971 | if (sc->sc_dk.dk_openmask == 0) { | 1966 | if (sc->sc_dk.dk_openmask == 0) { | |
1972 | 1967 | |||
1973 | if (! (sc->sc_flags & EFLASHF_KLABEL)) | 1968 | if (! (sc->sc_flags & EFLASHF_KLABEL)) | |
1974 | sc->sc_flags &= ~EFLASHF_LOADED; | 1969 | sc->sc_flags &= ~EFLASHF_LOADED; | |
1975 | 1970 | |||
1976 | DEBUG_PRINT(("%s: eflashclose flg %x\n", device_xname(sc->sc_dev), sc->sc_flags), | 1971 | DEBUG_PRINT(("%s: eflashclose flg %x\n", device_xname(sc->sc_dev), sc->sc_flags), | |
1977 | DEBUG_XFERS); | 1972 | DEBUG_XFERS); | |
1978 | 1973 | |||
1979 | } | 1974 | } | |
1980 | 1975 | |||
1981 | mutex_exit(&sc->sc_dk.dk_openlock); | 1976 | mutex_exit(&sc->sc_dk.dk_openlock); | |
1982 | return 0; | 1977 | return 0; | |
1983 | } | 1978 | } | |
1984 | 1979 | |||
1985 | void | 1980 | void | |
1986 | eflashgetdefaultlabel(struct eflash_softc *sc, struct disklabel *lp) | 1981 | eflashgetdefaultlabel(struct eflash_softc *sc, struct disklabel *lp) | |
1987 | { | 1982 | { | |
1988 | 1983 | |||
1989 | DEBUG_PRINT(("%s: eflashgetdefaultlabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS); | 1984 | DEBUG_PRINT(("%s: eflashgetdefaultlabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS); | |
1990 | memset(lp, 0, sizeof(struct disklabel)); | 1985 | memset(lp, 0, sizeof(struct disklabel)); | |
1991 | 1986 | |||
1992 | lp->d_secsize = DEV_BSIZE; | 1987 | lp->d_secsize = DEV_BSIZE; | |
1993 | lp->d_ntracks = 1; | 1988 | lp->d_ntracks = 1; | |
1994 | lp->d_nsectors = sc->sc_capacity; | 1989 | lp->d_nsectors = sc->sc_capacity; | |
1995 | lp->d_ncylinders = 1; | 1990 | lp->d_ncylinders = 1; | |
1996 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; | 1991 | lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; | |
1997 | 1992 | |||
1998 | lp->d_type = DKTYPE_ST506; /* ?!? */ | 1993 | lp->d_type = DKTYPE_ST506; /* ?!? */ | |
1999 | 1994 | |||
2000 | strncpy(lp->d_typename, ST506, 16); | 1995 | strncpy(lp->d_typename, ST506, 16); | |
2001 | strncpy(lp->d_packname, "fictitious", 16); | 1996 | strncpy(lp->d_packname, "fictitious", 16); | |
2002 | if (sc->sc_capacity > UINT32_MAX) | 1997 | if (sc->sc_capacity > UINT32_MAX) | |
2003 | lp->d_secperunit = UINT32_MAX; | 1998 | lp->d_secperunit = UINT32_MAX; | |
2004 | else | 1999 | else | |
2005 | lp->d_secperunit = sc->sc_capacity; | 2000 | lp->d_secperunit = sc->sc_capacity; | |
2006 | lp->d_rpm = 3600; | 2001 | lp->d_rpm = 3600; | |
2007 | lp->d_interleave = 1; | 2002 | lp->d_interleave = 1; | |
2008 | lp->d_flags = 0; | 2003 | lp->d_flags = 0; | |
2009 | 2004 | |||
2010 | lp->d_partitions[RAW_PART].p_offset = 0; | 2005 | lp->d_partitions[RAW_PART].p_offset = 0; | |
2011 | lp->d_partitions[RAW_PART].p_size = | 2006 | lp->d_partitions[RAW_PART].p_size = | |
2012 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); | 2007 | lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); | |
2013 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; | 2008 | lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; | |
2014 | lp->d_npartitions = RAW_PART + 1; | 2009 | lp->d_npartitions = RAW_PART + 1; | |
2015 | 2010 | |||
2016 | lp->d_magic = DISKMAGIC; | 2011 | lp->d_magic = DISKMAGIC; | |
2017 | lp->d_magic2 = DISKMAGIC; | 2012 | lp->d_magic2 = DISKMAGIC; | |
2018 | lp->d_checksum = dkcksum(lp); | 2013 | lp->d_checksum = dkcksum(lp); | |
2019 | } | 2014 | } | |
2020 | 2015 | |||
2021 | /* | 2016 | /* | |
2022 | * Fabricate a default disk label, and try to read the correct one. | 2017 | * Fabricate a default disk label, and try to read the correct one. | |
2023 | */ | 2018 | */ | |
2024 | void | 2019 | void | |
2025 | eflashgetdisklabel(struct eflash_softc *sc) | 2020 | eflashgetdisklabel(struct eflash_softc *sc) | |
2026 | { | 2021 | { | |
2027 | struct disklabel *lp = sc->sc_dk.dk_label; | 2022 | struct disklabel *lp = sc->sc_dk.dk_label; | |
2028 | const char *errstring; | 2023 | const char *errstring; | |
2029 | 2024 | |||
2030 | DEBUG_PRINT(("%s: eflashgetdisklabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS); | 2025 | DEBUG_PRINT(("%s: eflashgetdisklabel\n", device_xname(sc->sc_dev)), DEBUG_FUNCS); | |
2031 | 2026 | |||
2032 | memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); | 2027 | memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); | |
2033 | 2028 | |||
2034 | eflashgetdefaultlabel(sc, lp); | 2029 | eflashgetdefaultlabel(sc, lp); | |
2035 | 2030 | |||
2036 | #ifdef HAS_BAD144_HANDLING | 2031 | #ifdef HAS_BAD144_HANDLING | |
2037 | sc->sc_bio.badsect[0] = -1; | 2032 | sc->sc_bio.badsect[0] = -1; | |
2038 | #endif | 2033 | #endif | |
2039 | 2034 | |||
2040 | /* BUGBUG: maj==0?? why is this not EFLASHLABELDEV(??sc->sc_dev) */ | 2035 | /* BUGBUG: maj==0?? why is this not EFLASHLABELDEV(??sc->sc_dev) */ | |
2041 | errstring = readdisklabel(MAKEEFLASHDEV(0, device_unit(sc->sc_dev), | 2036 | errstring = readdisklabel(MAKEEFLASHDEV(0, device_unit(sc->sc_dev), | |
2042 | RAW_PART), eflashstrategy, lp, | 2037 | RAW_PART), eflashstrategy, lp, | |
2043 | sc->sc_dk.dk_cpulabel); | 2038 | sc->sc_dk.dk_cpulabel); | |
2044 | if (errstring) { | 2039 | if (errstring) { | |
2045 | printf("%s: %s\n", device_xname(sc->sc_dev), errstring); | 2040 | printf("%s: %s\n", device_xname(sc->sc_dev), errstring); | |
2046 | return; | 2041 | return; | |
2047 | } | 2042 | } | |
2048 | 2043 | |||
2049 | #if DEBUG | 2044 | #if DEBUG | |
2050 | if (EFLASH_DEBUG(DEBUG_WRITES)) { | 2045 | if (EFLASH_DEBUG(DEBUG_WRITES)) { | |
2051 | int i, n = sc->sc_dk.dk_label->d_npartitions; | 2046 | int i, n = sc->sc_dk.dk_label->d_npartitions; | |
2052 | printf("%s: %d parts\n", device_xname(sc->sc_dev), n); | 2047 | printf("%s: %d parts\n", device_xname(sc->sc_dev), n); | |
2053 | for (i = 0; i < n; i++) { | 2048 | for (i = 0; i < n; i++) { | |
2054 | printf("\t[%d]: t=%x s=%d o=%d\n", i, | 2049 | printf("\t[%d]: t=%x s=%d o=%d\n", i, | |
2055 | sc->sc_dk.dk_label->d_partitions[i].p_fstype, | 2050 | sc->sc_dk.dk_label->d_partitions[i].p_fstype, | |
2056 | sc->sc_dk.dk_label->d_partitions[i].p_size, | 2051 | sc->sc_dk.dk_label->d_partitions[i].p_size, | |
2057 | sc->sc_dk.dk_label->d_partitions[i].p_offset); | 2052 | sc->sc_dk.dk_label->d_partitions[i].p_offset); | |
2058 | } | 2053 | } | |
2059 | } | 2054 | } | |
2060 | #endif | 2055 | #endif | |
2061 | 2056 | |||
2062 | #ifdef HAS_BAD144_HANDLING | 2057 | #ifdef HAS_BAD144_HANDLING | |
2063 | if ((lp->d_flags & D_BADSECT) != 0) | 2058 | if ((lp->d_flags & D_BADSECT) != 0) | |
2064 | bad144intern(sc); | 2059 | bad144intern(sc); | |
2065 | #endif | 2060 | #endif | |
2066 | } | 2061 | } | |
2067 | 2062 | |||
2068 | void | 2063 | void | |
2069 | eflashperror(const struct eflash_softc *sc) | 2064 | eflashperror(const struct eflash_softc *sc) | |
2070 | { | 2065 | { | |
2071 | const char *devname = device_xname(sc->sc_dev); | 2066 | const char *devname = device_xname(sc->sc_dev); | |
2072 | u_int32_t Status = sc->sc_bio.r_error; | 2067 | u_int32_t Status = sc->sc_bio.r_error; | |
2073 | 2068 | |||
2074 | printf("%s: (", devname); | 2069 | printf("%s: (", devname); | |
2075 | 2070 | |||
2076 | if (Status == 0) | 2071 | if (Status == 0) | |
2077 | printf("error not notified"); | 2072 | printf("error not notified"); | |
2078 | else | 2073 | else | |
2079 | printf("status=x%x", Status); | 2074 | printf("status=x%x", Status); | |
2080 | 2075 | |||
2081 | printf(")\n"); | 2076 | printf(")\n"); | |
2082 | } | 2077 | } | |
2083 | 2078 | |||
2084 | int | 2079 | int | |
2085 | eflashioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l) | 2080 | eflashioctl(dev_t dev, u_long xfer, void *addr, int flag, struct lwp *l) | |
2086 | { | 2081 | { | |
2087 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | 2082 | struct eflash_softc *sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | |
2088 | int error = 0, s; | 2083 | int error = 0, s; | |
2089 | 2084 | |||
2090 | DEBUG_PRINT(("eflashioctl(%lx)\n",xfer), DEBUG_FUNCS); | 2085 | DEBUG_PRINT(("eflashioctl(%lx)\n",xfer), DEBUG_FUNCS); | |
2091 | 2086 | |||
2092 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) | 2087 | if ((sc->sc_flags & EFLASHF_LOADED) == 0) | |
2093 | return EIO; | 2088 | return EIO; | |
2094 | 2089 | |||
2095 | error = disk_ioctl(&sc->sc_dk, dev, xfer, addr, flag, l); | 2090 | error = disk_ioctl(&sc->sc_dk, dev, xfer, addr, flag, l); | |
2096 | if (error != EPASSTHROUGH) | 2091 | if (error != EPASSTHROUGH) | |
2097 | return (error); | 2092 | return (error); | |
2098 | 2093 | |||
2099 | switch (xfer) { | 2094 | switch (xfer) { | |
2100 | #ifdef HAS_BAD144_HANDLING | 2095 | #ifdef HAS_BAD144_HANDLING | |
2101 | case DIOCSBAD: | 2096 | case DIOCSBAD: | |
2102 | if ((flag & FWRITE) == 0) | 2097 | if ((flag & FWRITE) == 0) | |
2103 | return EBADF; | 2098 | return EBADF; | |
2104 | sc->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; | 2099 | sc->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; | |
2105 | sc->sc_dk.dk_label->d_flags |= D_BADSECT; | 2100 | sc->sc_dk.dk_label->d_flags |= D_BADSECT; | |
2106 | bad144intern(sc); | 2101 | bad144intern(sc); | |
2107 | return 0; | 2102 | return 0; | |
2108 | #endif | 2103 | #endif | |
2109 | 2104 | |||
2110 | case DIOCWDINFO: | 2105 | case DIOCWDINFO: | |
2111 | case DIOCSDINFO: | 2106 | case DIOCSDINFO: | |
2112 | { | 2107 | { | |
2113 | struct disklabel *lp; | 2108 | struct disklabel *lp; | |
2114 | 2109 | |||
2115 | if ((flag & FWRITE) == 0) | 2110 | if ((flag & FWRITE) == 0) | |
2116 | return EBADF; | 2111 | return EBADF; | |
2117 | 2112 | |||
2118 | lp = (struct disklabel *)addr; | 2113 | lp = (struct disklabel *)addr; | |
2119 | 2114 | |||
2120 | mutex_enter(&sc->sc_dk.dk_openlock); | 2115 | mutex_enter(&sc->sc_dk.dk_openlock); | |
2121 | sc->sc_flags |= EFLASHF_LABELLING; | 2116 | sc->sc_flags |= EFLASHF_LABELLING; | |
2122 | 2117 | |||
2123 | error = setdisklabel(sc->sc_dk.dk_label, | 2118 | error = setdisklabel(sc->sc_dk.dk_label, | |
2124 | lp, /*sc->sc_dk.dk_openmask : */0, | 2119 | lp, /*sc->sc_dk.dk_openmask : */0, | |
2125 | sc->sc_dk.dk_cpulabel); | 2120 | sc->sc_dk.dk_cpulabel); | |
2126 | if (error == 0) { | 2121 | if (error == 0) { | |
2127 | if (xfer == DIOCWDINFO) | 2122 | if (xfer == DIOCWDINFO) | |
2128 | error = writedisklabel(EFLASHLABELDEV(dev), | 2123 | error = writedisklabel(EFLASHLABELDEV(dev), | |
2129 | eflashstrategy, sc->sc_dk.dk_label, | 2124 | eflashstrategy, sc->sc_dk.dk_label, | |
2130 | sc->sc_dk.dk_cpulabel); | 2125 | sc->sc_dk.dk_cpulabel); | |
2131 | } | 2126 | } | |
2132 | 2127 | |||
2133 | sc->sc_flags &= ~EFLASHF_LABELLING; | 2128 | sc->sc_flags &= ~EFLASHF_LABELLING; | |
2134 | mutex_exit(&sc->sc_dk.dk_openlock); | 2129 | mutex_exit(&sc->sc_dk.dk_openlock); | |
2135 | return error; | 2130 | return error; | |
2136 | } | 2131 | } | |
2137 | 2132 | |||
2138 | case DIOCKLABEL: | 2133 | case DIOCKLABEL: | |
2139 | if (*(int *)addr) | 2134 | if (*(int *)addr) | |
2140 | sc->sc_flags |= EFLASHF_KLABEL; | 2135 | sc->sc_flags |= EFLASHF_KLABEL; | |
2141 | else | 2136 | else | |
2142 | sc->sc_flags &= ~EFLASHF_KLABEL; | 2137 | sc->sc_flags &= ~EFLASHF_KLABEL; | |
2143 | return 0; | 2138 | return 0; | |
2144 | 2139 | |||
2145 | case DIOCWLABEL: | 2140 | case DIOCWLABEL: | |
2146 | if ((flag & FWRITE) == 0) | 2141 | if ((flag & FWRITE) == 0) | |
2147 | return EBADF; | 2142 | return EBADF; | |
2148 | if (*(int *)addr) | 2143 | if (*(int *)addr) | |
2149 | sc->sc_flags |= EFLASHF_WLABEL; | 2144 | sc->sc_flags |= EFLASHF_WLABEL; | |
2150 | else | 2145 | else | |
2151 | sc->sc_flags &= ~EFLASHF_WLABEL; | 2146 | sc->sc_flags &= ~EFLASHF_WLABEL; | |
2152 | return 0; | 2147 | return 0; | |
2153 | 2148 | |||
2154 | case DIOCGDEFLABEL: | 2149 | case DIOCGDEFLABEL: | |
2155 | eflashgetdefaultlabel(sc, (struct disklabel *)addr); | 2150 | eflashgetdefaultlabel(sc, (struct disklabel *)addr); | |
2156 | return 0; | 2151 | return 0; | |
2157 | 2152 | |||
2158 | case DIOCCACHESYNC: | 2153 | case DIOCCACHESYNC: | |
2159 | return 0; | 2154 | return 0; | |
2160 | 2155 | |||
2161 | case DIOCGSTRATEGY: | 2156 | case DIOCGSTRATEGY: | |
2162 | { | 2157 | { | |
2163 | struct disk_strategy *dks = (void *)addr; | 2158 | struct disk_strategy *dks = (void *)addr; | |
2164 | 2159 | |||
2165 | s = splbio(); | 2160 | s = splbio(); | |
2166 | strlcpy(dks->dks_name, bufq_getstrategyname(sc->sc_q), | 2161 | strlcpy(dks->dks_name, bufq_getstrategyname(sc->sc_q), | |
2167 | sizeof(dks->dks_name)); | 2162 | sizeof(dks->dks_name)); | |
2168 | splx(s); | 2163 | splx(s); | |
2169 | dks->dks_paramlen = 0; | 2164 | dks->dks_paramlen = 0; | |
2170 | 2165 | |||
2171 | return 0; | 2166 | return 0; | |
2172 | } | 2167 | } | |
2173 | 2168 | |||
2174 | case DIOCSSTRATEGY: | 2169 | case DIOCSSTRATEGY: | |
2175 | { | 2170 | { | |
2176 | struct disk_strategy *dks = (void *)addr; | 2171 | struct disk_strategy *dks = (void *)addr; | |
2177 | struct bufq_state *new; | 2172 | struct bufq_state *new; | |
2178 | struct bufq_state *old; | 2173 | struct bufq_state *old; | |
2179 | 2174 | |||
2180 | if ((flag & FWRITE) == 0) { | 2175 | if ((flag & FWRITE) == 0) { | |
2181 | return EBADF; | 2176 | return EBADF; | |
2182 | } | 2177 | } | |
2183 | if (dks->dks_param != NULL) { | 2178 | if (dks->dks_param != NULL) { | |
2184 | return EINVAL; | 2179 | return EINVAL; | |
2185 | } | 2180 | } | |
2186 | dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ | 2181 | dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */ | |
2187 | error = bufq_alloc(&new, dks->dks_name, | 2182 | error = bufq_alloc(&new, dks->dks_name, | |
2188 | BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); | 2183 | BUFQ_EXACT|BUFQ_SORT_RAWBLOCK); | |
2189 | if (error) { | 2184 | if (error) { | |
2190 | return error; | 2185 | return error; | |
2191 | } | 2186 | } | |
2192 | s = splbio(); | 2187 | s = splbio(); | |
2193 | old = sc->sc_q; | 2188 | old = sc->sc_q; | |
2194 | bufq_move(new, old); | 2189 | bufq_move(new, old); | |
2195 | sc->sc_q = new; | 2190 | sc->sc_q = new; | |
2196 | splx(s); | 2191 | splx(s); | |
2197 | bufq_free(old); | 2192 | bufq_free(old); | |
2198 | 2193 | |||
2199 | return 0; | 2194 | return 0; | |
2200 | } | 2195 | } | |
2201 | 2196 | |||
2202 | default: | 2197 | default: | |
2203 | /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */ | 2198 | /* NB: we get a DIOCGWEDGEINFO, but nobody else handles it either */ | |
2204 | DEBUG_PRINT(("eflashioctl: unsup x%lx\n", xfer), DEBUG_FUNCS); | 2199 | DEBUG_PRINT(("eflashioctl: unsup x%lx\n", xfer), DEBUG_FUNCS); | |
2205 | return ENOTTY; | 2200 | return ENOTTY; | |
2206 | } | 2201 | } | |
2207 | } | 2202 | } | |
2208 | 2203 | |||
2209 | int | 2204 | int | |
2210 | eflashsize(dev_t dev) | 2205 | eflashsize(dev_t dev) | |
2211 | { | 2206 | { | |
2212 | struct eflash_softc *sc; | 2207 | struct eflash_softc *sc; | |
2213 | int part, omask; | 2208 | int part, omask; | |
2214 | int size; | 2209 | int size; | |
2215 | 2210 | |||
2216 | DEBUG_PRINT(("eflashsize\n"), DEBUG_FUNCS); | 2211 | DEBUG_PRINT(("eflashsize\n"), DEBUG_FUNCS); | |
2217 | 2212 | |||
2218 | sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | 2213 | sc = device_lookup_private(&eflash_cd, EFLASHUNIT(dev)); | |
2219 | if (sc == NULL) | 2214 | if (sc == NULL) | |
2220 | return (-1); | 2215 | return (-1); | |
2221 | 2216 | |||
2222 | part = EFLASHPART(dev); | 2217 | part = EFLASHPART(dev); | |
2223 | omask = sc->sc_dk.dk_openmask & (1 << part); | 2218 | omask = sc->sc_dk.dk_openmask & (1 << part); | |
2224 | 2219 | |||
2225 | if (omask == 0 && eflashopen(dev, 0, S_IFBLK, NULL) != 0) | 2220 | if (omask == 0 && eflashopen(dev, 0, S_IFBLK, NULL) != 0) | |
2226 | return (-1); | 2221 | return (-1); | |
2227 | if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) | 2222 | if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) | |
2228 | size = -1; | 2223 | size = -1; | |
2229 | else | 2224 | else | |
2230 | size = sc->sc_dk.dk_label->d_partitions[part].p_size * | 2225 | size = sc->sc_dk.dk_label->d_partitions[part].p_size * | |
2231 | (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE); | 2226 | (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE); | |
2232 | if (omask == 0 && eflashclose(dev, 0, S_IFBLK, NULL) != 0) | 2227 | if (omask == 0 && eflashclose(dev, 0, S_IFBLK, NULL) != 0) | |
2233 | return (-1); | 2228 | return (-1); | |
2234 | return (size); | 2229 | return (size); | |
2235 | } | 2230 | } | |
2236 | 2231 | |||
2237 | /* | 2232 | /* | |
2238 | * Dump core after a system crash. | 2233 | * Dump core after a system crash. | |
2239 | */ | 2234 | */ | |
2240 | int | 2235 | int | |
2241 | eflashdump(dev_t dev, daddr_t blkno, void *va, size_t size) | 2236 | eflashdump(dev_t dev, daddr_t blkno, void *va, size_t size) | |
2242 | { | 2237 | { | |
2243 | /* no we dont */ | 2238 | /* no we dont */ | |
2244 | return (ENXIO); | 2239 | return (ENXIO); | |
2245 | } | 2240 | } | |
2246 | 2241 | |||
2247 | #ifdef HAS_BAD144_HANDLING | 2242 | #ifdef HAS_BAD144_HANDLING | |
2248 | /* | 2243 | /* | |
2249 | * Internalize the bad sector table. | 2244 | * Internalize the bad sector table. | |
2250 | */ | 2245 | */ | |
2251 | void | 2246 | void | |
2252 | bad144intern(struct eflash_softc *sc) | 2247 | bad144intern(struct eflash_softc *sc) | |
2253 | { | 2248 | { | |
2254 | struct dkbad *bt = &sc->sc_dk.dk_cpulabel->bad; | 2249 | struct dkbad *bt = &sc->sc_dk.dk_cpulabel->bad; | |
2255 | struct disklabel *lp = sc->sc_dk.dk_label; | 2250 | struct disklabel *lp = sc->sc_dk.dk_label; | |
2256 | int i = 0; | 2251 | int i = 0; | |
2257 | 2252 | |||
2258 | DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); | 2253 | DEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); | |
2259 | 2254 | |||
2260 | for (; i < NBT_BAD; i++) { | 2255 | for (; i < NBT_BAD; i++) { | |
2261 | if (bt->bt_bad[i].bt_cyl == 0xffff) | 2256 | if (bt->bt_bad[i].bt_cyl == 0xffff) | |
2262 | break; | 2257 | break; | |
2263 | sc->sc_bio.badsect[i] = | 2258 | sc->sc_bio.badsect[i] = | |
2264 | bt->bt_bad[i].bt_cyl * lp->d_secpercyl + | 2259 | bt->bt_bad[i].bt_cyl * lp->d_secpercyl + | |
2265 | (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + | 2260 | (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + | |
2266 | (bt->bt_bad[i].bt_trksec & 0xff); | 2261 | (bt->bt_bad[i].bt_trksec & 0xff); | |
2267 | } | 2262 | } | |
2268 | for (; i < NBT_BAD+1; i++) | 2263 | for (; i < NBT_BAD+1; i++) | |
2269 | sc->sc_bio.badsect[i] = -1; | 2264 | sc->sc_bio.badsect[i] = -1; | |
2270 | } | 2265 | } | |
2271 | #endif | 2266 | #endif | |
2272 | 2267 | |||
2273 | static void | 2268 | static void | |
2274 | eflash_set_geometry(struct eflash_softc *sc) | 2269 | eflash_set_geometry(struct eflash_softc *sc) | |
2275 | { | 2270 | { | |
2276 | struct disk_geom *dg = &sc->sc_dk.dk_geom; | 2271 | struct disk_geom *dg = &sc->sc_dk.dk_geom; | |
2277 | 2272 | |||
2278 | memset(dg, 0, sizeof(*dg)); | 2273 | memset(dg, 0, sizeof(*dg)); | |
2279 | 2274 | |||
2280 | dg->dg_secperunit = sc->sc_capacity; | 2275 | dg->dg_secperunit = sc->sc_capacity; | |
2281 | dg->dg_secsize = DEV_BSIZE /* XXX 512? */; | 2276 | dg->dg_secsize = DEV_BSIZE /* XXX 512? */; | |
2282 | dg->dg_nsectors = sc->sc_capacity; | 2277 | dg->dg_nsectors = sc->sc_capacity; | |
2283 | dg->dg_ntracks = 1; | 2278 | dg->dg_ntracks = 1; | |
2284 | dg->dg_ncylinders = sc->sc_capacity; | 2279 | dg->dg_ncylinders = sc->sc_capacity; | |
2285 | 2280 | |||
2286 | disk_set_info(sc->sc_dev, &sc->sc_dk, ST506); | 2281 | disk_set_info(sc->sc_dev, &sc->sc_dk, ST506); | |
2287 | } | 2282 | } |